I am having a Servlet A which defines a local variable say a1 in one of its method as shown below. There is another class B for which object is created in Servlet A and that object calls the method and do operation.
Which one of these variable a1 and a2 is thread safe and why? I believe that a1 is thread safe since that is local to class A and a2 is not thread safe since that is behaving as a member variable.
class Servlet A {
public void method1(){
String a1;
B b = new b();
String c = b.method2(a1);
}
}
class B {
String a2;
public String method2(String a1){
// do operations on a1 and a2
return a1+a2;
}
}
You are right. Method-scoped variables (local variables) are thread safe, because they live on stack and couldn't be accessed by other threads.
Member variables (fields) live on heap and are not thread-safe, because they could be accessed simultaneously by multiple threads.
Related
I have recently begun to understand how the Java Memory Model works (I don't fully yet).
I now understand that if I have non-final, non-volatile fields in my classes then it is possible for the value of those fields to not be immediately visible to other threads post construction e.g.
public class Example {
Object a;
Object b;
public Example() {
this.a = new Object();
this.b = new Object();
}
}
Example e = new Example();
// now imagine we are in another thread
e.a // could this in theory be null?
e.b // could this in theory be null?
What I'm not sure about is weather if I add a third volatile variable and set it at the end will the writes to a and b be guaranteed to be visible to other threads?
public class Example2 {
Object a;
Object b;
volatile Object c;
public Example2() {
this.a = new Object();
this.b = new Object();
this.c = new Object();
}
}
// some where else
Example2 e2 = new Example2();
// are e2.a and e2.b guaranteed to be visible to all other threads? I know (e2.c will be)
This is not something I particularly want to use but I want to understand what would happen in this case.
The constructor runs in a single thread and the instance is not "visible" to other threads until the constructor completes.
So, in this example, a and b will only be seen in other threads as null if they are subsequently set to null post-constructor.
The volatile keyword addresses possible optimizations in which a thread may continue to use an old value for a field after it changes on another thread due to local caching of the value. By adding volatile to the field, such optimizations are disabled.
By the way, if there's a need to synchronize across threads, using volatile fields is not ideal. Using atomic classes or other constructs from java.util.concurrent is advisable.
This is a sample code which i wrote this just for you to understand my problem which writtens below.
This is class which has a examplemethod which calculate some value for different a;
public class Class1{
public int examplemethod(int a){
int k = a*2;
int b=k+1;
......some more manipulation
return k;
}
}
Below class will call the above method parallely
public class Class2 extends RecursiveTask<Integer>{
int a=0;
Class1 obj;
public Class2(int a, Class1 obj){
this.a = a;
this.obj=obj;
}
#Override
protected Integer compute () {
return obj.examplemethod(a);
}
public static void main(Strings[] args){
List<Class2> list =new ArrayList<Class2>();
Class1 obj = new Class1();
for(int i=4;i<7;i++){
Class2 obj2=new Class2(obj);
obj2.fork();
list.add(obj2);
}
int arr[]=new int[4];
int i=0;
if(list.size>0){
for(Class2 ob:list){
arr[i++]= ob.join();
}
}
}
}
I am creating three object of class2 in the for loop so suppose 1st fork will compute the value using a=4 but while it is computing in the examplemethod, cpu shedule another thread let say fork 2 with a=5 and save program counter for fork 1 thread, now while computing value using a=5 it changes some variable inside the examplemethod which was earlier changes by fork1, so now my problem is, if examplemethod is resource which was shared among all the object of that class and if one object do some changes in the function and in the middle(thread switching) some other object came and change the same variable then my output will get affected but the problem is i am getting the right answer, so where my concept lagging in parallel threading, Threads will share a common resource so where is my critical section in my code.
Variables declared inside a method are local variables, having specific values for the particular method invocation. You should understand that concept independently of multi threading aspects first. E.g. what will the following program print:
public class Test {
public static void main(String[] args) {
test(5);
}
private static void test(int i) {
System.out.println("enter test with "+i);
if(i>0) test(i-1);
System.out.println("leave test with "+i);
}
}
The local nature of these variables doesn’t change when multiple threads execute the same method. There is no interference between these executions.
Likewise, instance variables, i.e. member variables declared in a class without the static modifier. hold values specific to a particular object instance, hence, if you create multiple instances, they can have distinct values for these variables without affecting each other.
These are the building blocks which are used to build multi-threaded programs without the need to do thread synchronization all the time. If you create distinct objects representing the different tasks to be executed and these tasks execute only methods using these objects and/or their method parameters (method parameters are local variables) to compute results, the tasks are already isolated.
The things you must not do, are modifying static variables or instance variables of shared objects. In your code, there are no shared objects.
Which resource is shared between threads in your code?
in short your class1 is thread safe, because variables defined inside method cannot be changed by another thread.
While class2 is not - if and only if two threads can use same instance of class2 at the same time (aka Singleton) and thread changes some instance variable, while another one use it.
You have only one instance variable in class2 - int a.
But in the code I do not see any kind of Singleton or instance variable "a"change...
Each thread has a new instance of class2: Class2 obj2=new Class2();
(actually it must be kind of Class2 obj2=new Class2(aValue);)
Did I miss something there?
I have two classes A and B:
class A {
private final String someData;
private B b;
public String getSomeData() { return someData; }
public B getB() {
if (b == null) {
b = new B(someData);
}
return b;
}
}
where B is immutable and computes its data only from an instance of A. A has immutable semantics, but it's internals are mutable (like hashCode in java.lang.String).
When I call getB() from two different threads, and the calls overlap, I assume each thread gets its own instance of B. But since the constructor of B gets only immutable data, the two instances of B should be equal.
Is that correct? If not, must I make getB() synchronized to make it thread-safe?
Assume that B implements equals(), which compares all instance variables of B. Same for hashCode()
This is not thread-safe, because you haven't created any "happens-before" relationships with volatile or synchronized, so it's possible for the two threads to interfere with each other.
The problem is that although b = new B(someData) means "allocate enough memory for an instance of B, then create the instance there, then point b to it", the system is allowed to implement it as "allocate enough memory for an instance of B, then point b to it, then create the instance" (since, in a single-threaded app, that's equivalent). So in your code, where two threads can create separate instances but return the same instance, there's a chance that one thread will return the other thread's instance before the instance is fully initialized.
For "But since the constructor of B gets only immutable data, the two instances of B should be equal."
As you understand its not thread safe, one thread might get un-initialized B instance (B as null or inconsistent state where somedata not yet set) others might get b instance with somedata set.
To fix this you need synchronized getB method or use synchronized block with double-check lock or some non-blocking technique like AtomicReference. For you reference I am adding here sample code for how to achieve the correct threadSafe getB() method using AtomicReference.
class A {
private final String someData = "somedata";
private AtomicReference<B> bRef;
public String getSomeData() { return someData; }
public B getB() {
if(bRef.get()== null){
synchronized (this){
if(bRef.get() == null)
bRef.compareAndSet(null,new B(someData));
}
}
return bRef.get();
}
}
class B{
public B(String someData) {
}
}
Consider below scenario, it says if str is volatile it means any update by any thread accessing str, will directly update on main stack instead of local Thread cache.
class A{
volatile String str;
volatile B b=new B();
}
class B{
int a;
C c;
}
For b volatile object, how scenario will work?
I read few links it says only reference is volatile and not the property of object itself, what does that mean, can some one help me with some example as I am finding it little bit difficult to understand.
if reference is synchronized, then how it will help, what is the use of it?
First scenario:
thread 1 does a.b = new B();
then thread 2 does B b = a.b;
In this case, you have the guarantee that the object referenced by b in the second thread is the new B() that the first thread has assigned to the variable.
Second scenario:
thread 1 does a.b.setFoo("hello");
then thread 2 does String s = a.b.getFoo();
In this case, you have no guarantee regarding the value of s in the second thread. It could be "hello", or it could be a previous value of a.b.foo (unless the foo attribute in class B is itself volatile, or the setters and getters are synchronized).
I have:
public class UTIL{
public static void met(){
do_something(){
print(A.m());
}
}
}
public class A{
public <type> m;
public <type>static m(){
return m;
}
}
Now:
Thread A contains instance of class A
Thread B contains instance of class A
From Thread B, at some point UTIL.met is called.
Question:
When UTIL.met is called, will it use m from the instance of A in Thread B?
When UTIL.met is called, will it use m from the instance of A in Thread B?
No, it doesn't matter if Thread A has one instance and Thread B has another. A.m is static and common for all instances.
But it is definitely the case that if the variables are static, then both threads will use the same variable.
(In other words, without proper synchronization, you'll have nasty race-conditions.)
m is a class variable, so is is actually common for all instances.
UTIL.met() will use the same instance of m that is "being held" [or can be accessed is a better terminology...] in all instances of A.
m is defined as a static variable in A. So it will common/shared among all instances of A.
If m is not static on the other hand, then of course each instance will have its own copy.
Well since thread A and thread B each contains own instance of class A, then each thread will use its instance of A.
is that what you want to achieve or you wanted to share m between instances??