I'd like to understand how static context work in multithread env.
If you have a static method in a class, lets say "ContainerClass.notSafeStaticMethod();" and you call it from different threads at the same time.
Are the variables inside the method shared?
public class ContainerClass{
public static String notSafeStaticMethod(String stringParameter) {
String localString = stringParameter + "1";
localString += "2";
localString += "3";
return localString;
}
}
Then two threads call it at the same time:
ContainerClass.notSafeStaticMethod( "first Call"); /*Thread 1 is executing*/
ContainerClass.notSafeStaticMethod( "Second Call"); /*Thread 2 starts executing before thread 1 finishes*/
What would happen with the internal state of the function? also, What would happen with the value of the parameter received?
Will be one different value for each or they share the same memory?
According to my understanding static variables are not in the stack but the heap, so they should share them and hence the code wouldn't be thread safe, Is it right?
Local variables are isolated. This includes method parameters. Each thread has its own stack and local variables related to method calls in that thread are stored on that thread's stack memory.
So, for method notSafeStaticMethod, neither of the 2 threads will see the other's (local variables') values or be able to manipulate them, regardless of the relative timing of the two calls.
Care is needed only for shared variables (for example, if localString is declared as static field in the class, or shared variables passed as method arguments), where threads can overwrite one another's changes unless proper synchronization is done.
The variables declared inside the static method are not static variables, they are local variables, and they are on the stack for that thread (though reference variables point to locations on the heap), in a stackframe dedicated to a specific method call. So there is no opportunity for other threads to interfere, each method invocation is isolated.
Now if there are static variables used by a static method then those can be accessed concurrently. static variables are declared in a class using the keyword static. So make sure you can identify static variables.
Btw, nested classes can be marked as static, that means only that objects of that class don't have a reference back to an object of the class they're declared as nested inside of (see java.util.Map.Entry for an example). static in this context doesn't mean variables or methods in the class are static. That's just the Java implementers reusing an existing keyword so they don't risk breaking pre-existing code.
public class Example {
static int staticVariableHere;
public static int staticMethodHere(String methodArg) {
int localVariable = 42;
return localVariable;
}
}
Related
Inner classes only have access to final or effectively final variables. I don't understand though, why an instance variable can be accessed no matter what, but local variables and method parameters need to be at minimum effectively final?
Consider the following code:
public class BookStore {
private static final int taxId = 300000;
public String name;
public String searchBook(final String criteria) {
int count = 0;
int sum = 0;
// name = ""; I can uncomment this -> no compile error
class Enumerator {
String interate(int k) {
System.out.println(name);
System.out.println(sum);
return "";
}
}
// sum++; If I uncomment this, a compile error will be thrown.
return "";
}
}
Why is it necessary that local variables + method arguments need to be effectively final?
It’s all about the value which is captured when the instance is created. Inner classes in an instance context always capture the immutable outer this reference¹, through which the instance fields can be accessed, mutable or not. In contrast, local variables can only be captured by their value, hence, the variable must not change, to be consistent with the captured value.
This is a design decision. Technically, it would be no problem to a) allow subsequent mutations that are not reflected by the inner class’ state or b) wrap every shared local variable into an object to allow mutations like with instance fields of the outer class, but neither, allowed inconsistency nor local variables that aren’t actually local, were deemed acceptable by the language designers.
¹ This differs from lambda expressions which only capture this when actually accessing instance variables
It's because of the scope of the local variables. Their scope is the method in which they are declared. Once execution has left the method, they are no longer valid. However, an inner class such as your Enumerator class can live on past the method execution, e.g. by returning a reference to a class instance.
Thus, the Enumerator class and its methods can be accessed outside of the method in which it is declared. At that point, it needs to assume that the local variables it referenced have the same value they had when execution instantiated the class.
For instance variables, the scope of these and of the inner class is the same - they are both available as long as the parent class instance exists.
Suppose I have the following inner class, now method1() is accessed by 2 threads, say thread 1 and thread 2, here we are declaring a local variable and incrementing it.
Now this local variable is of primitive data type and will exist on stack, since each Thread has it's own memory stack it should not be shared between the threads, but int local is also a part of a static inner class, so I wanted to know whether int local will be shared between the threads or not?
As in if 2 threads simultaneously call the method1() how will the memory distribution be like?
private static class SharedClass {
int a = 0;
public void method1() {
int local = 0;
local++;
a=local;
}
}
Local variables are never shared with other threads in Java. It doesn't matter whether we are talking about ordinary methods, or lambdas. It doesn't matter whether the method is declared in a top level class, an inner class, a nested class, an anonymous class or a local classes.
So in your example, the two threads will have their own copies of the local variable, but they may be updating a shared a variable ... depending on which SharedClass instance they are calling the method on.
Or, to put it another way, you don't need to worry about thread safety for local = 0; and local++, but you do for access to a and the a=local; assignment.
There some scenario where local variables appear to be shared. However, it is an illusion. Consider this:
public void test() {
final int arg = 42;
new Thread(new Runnable(){
public void run() {
System.out.println(arg);
}
}).start();
}
It looks like the arg variable is accessed by the child thread. But in fact, what the child thread is actually accessing will be a synthetic variable in the Runnable instance whose value has been initialized to the value of arg; i.e. 42.
(If you compile the above code and use javap to examine the bytecodes, you will see how it works.)
Note that this is only allowed by the Java compiler when arg is final or effectively final. If was not final or effectively final, the trick of using a synthetic variable would not work.
As I understood static variables are visible/accessible among all threads in JAVA.
Is there a way to define a variable which is only accesible by classes within its thread?
If I correctly understand you intention, then yes, it is possible via ThreadLocal: https://docs.oracle.com/javase/8/docs/api/java/lang/ThreadLocal.html
This class provides thread-local variables. These variables differ
from their normal counterparts in that each thread that accesses one
(via its get or set method) has its own, independently initialized
copy of the variable. ThreadLocal instances are typically private
static fields in classes that wish to associate state with a thread
(e.g., a user ID or Transaction ID).
The answer to your question depends upon whether you mean "to define a variable", or "to define a value".
If you mean the latter, ThreadLocal, as suggested by #Andremoniy, is the right answer.
If you mean the former, no, you can't do this with a static variable. You can do it by defining member variables on classes, and making sure that instances of those classes are only accessible to particular threads. Trivially:
class MyThread extends Thread {
Object value;
#Override public void run() {
// Do something with value.
}
}
Now, that variable value is only accessible to its containing instance of MyThread. It is only accessible to other instances of MyThread if you share the reference to the MyThread with other threads. For example:
// In MyThread:
void swapValues(MyThread other) {
Object v = other.value;
other.value = this.value;
this.value = v;
}
I am trying to write an instance method to lazily initialise several static variables. The objects I am initialising are immutable, and the references for the objects are not changed by any other instance or static methods in the class. I want the initialization code to never be executed more than once even though there may be several instances of the class in many different threads. The initialization needs to take place in an instance method as the method overrides a method in a superclass. My approach I am using is as follows.
private static volatile boolean isPrepared;
private static volatile Object object1;
private static volatile Object object2;
private static volatile Object object3;
#Override
void prepare() {
synchronized (this.getClass()) {
if (isPrepared) { return; }
object1 = expensiveCalculation1();
object2 = expensiveCalculation2();
object3 = expensiveCalculation3();
isPrepared = true;
}
}
I am assuming that since the initialization takes place in a single synchronized block, it would be impossible for an instance to ever observe isPrepared as being true unless object1, object2 and object3 are all non-null. I am also assuming that it wouldn't work by simply declaring prepare() as synchronized as the lock would just be this. Are my assumptions right? Also, is it a good idea to have several variables marked volatile when you want to regard them as being initialised together, or should I bundle them together into a single Immutable class?
Bundling all lazily-initialized state into an immutable object is usually the preferred approach because then all you need is a volatile variable, with no synchronization. That arrangement opens you to some duplicated effort if another thread starts initializing while initialization is in progress, but the chances of that can be minimized, such as by writing a sentinel value to the volatile to signal the "in progress" state.
You can use next approach: https://stackoverflow.com/a/11879164/2413618
Put your variables into static nested class. When nested class will be accessed first time then all variables will be initialized.
I would like to known if each instance of a class has its own copy of the methods in that class?
Lets say, I have following class MyClass:
public MyClass {
private String s1;
private String s2;
private String method1(String s1){
...
}
private String method2(String s2){
...
}
}
So if two differents users make an instance of MyClass like:
MyClass instanceOfUser1 = new MyClass();
MyClass instanceOfUser2 = new MyClass();
Does know each user have in his thread a copy of the methods of MyClass? If yes, the instance variables are then thread-safe, as long as only the instance methods manipulate them, right?
I am asking this question because I often read that instance variables are not thread-safe. And I can not see why it should be like that, when each user gets an instance by calling the new operator?
Each object gets its own copy of the class's instance variables - it's static variables that are shared between all instances of a class. The reason that instance variables are not necessarily thread-safe is that they might be simultaneously modified by multiple threads calling unsynchronized instance methods.
class Example {
private int instanceVariable = 0;
public void increment() {
instanceVariable++;
}
}
Now if two different threads call increment at the same then you've got a data race - instanceVariable might increment by 1 or 2 at the end of the two methods returning. You could eliminate this data race by adding the synchronized keyword to increment, or using an AtomicInteger instead of an int, etc, but the point is that just because each object gets its own copy of the class's instance variables does not necessarily mean that the variables are accessed in a thread-safe manner - this depends on the class's methods. (The exception is final immutable variables, which can't be accessed in a thread-unsafe manner, short of something goofy like a serialization hack.)
Issues with multi-threading arise primarily with static variables and instances of a class being accessed at the same time.
You shouldn't worry about methods in the class but more about the fields (meaning scoped at the class level). If multiple references to an instance of a class exist, different execution paths may attempt to access the instance at the same time, causing unintended consequences such as race conditions.
A class is basically a blueprint for making an instance of an object. When the object is instantiated it receives a spot in memory that is accessed by a reference. If more than one thread has a handle to this reference it can cause occurrences where the instance is accessed simultaneously, this will cause fields to be manipulated by both threads.
'Instance Variables are not thread safe' - this statement depends on the context.
It is true, if for example you are talking about Servlets. It is because, Servlets create only one instance and multiple threads access it. So in that case Instance Variables are not thread safe.
In the above simplified case, if you are creating new instance for each thread, then your instance variables are thread safe.
Hope this answers your question
A method is nothing but a set of instructions. Whichever thread calls the method, get a copy of those instructions. After that the execution begins. The method may use local variables which are method and thread-scoped, or it may use shared resources, like static resources, shared objects or other resources, which are visible across threads.
Each instance has its own set of instance variables. How would you detect whether every instance had a distinct "copy" of the methods? Wouldn't the difference be visible only by examining the state of the instance variables?
In fact, no, there is only one copy of the method, meaning the set of instructions executed when the method is invoked. But, when executing, an instance method can refer to the instance on which it's being invoked with the reserved identifier this. The this identifier refers to the current instance. If you don't qualify an instance variable (or method) with something else, this is implied.
For example,
final class Example {
private boolean flag;
public void setFlag(boolean value) {
this.flag = value;
}
public void setAnotherFlag(Example friend) {
friend.flag = this.flag;
}
}
There's only one copy of the bytes that make up the VM instructions for the setFlag() and setAnotherFlag() methods. But when they are invoked, this is set to the instance upon which the invocation occurred. Because this is implied for an unqualified variable, you could delete all the references to this in the example, and it would still function exactly the same.
However, if a variable is qualified, like friend.flag above, the variables of another instance can be referenced. This is how you can get into trouble in a multi-threaded program. But, as long as an object doesn't "escape" from one thread to be visible to others, there's nothing to worry about.
There are many situations in which an instance may be accessible from multiple classes. For example, if your instance is a static variable in another class, then all threads would share that instance, and you can get into big trouble that way. That's just the first way that pops into my mind...