When the answer said:
"The Java memory model does not guarantee any updates made to a field from one thread to be visible to another thread if the field is not accessed through a synchronized block".
First Question:
This is because of the cache system that JVM makes to increase performance? (copying the variables of Thread A in Thread B, and when Thread A changes, no guarantee that Thread B can see the changes)
public static final StaticSyncTest sst = new StaticSyncTest();
, then, we solve this problem mentioned in First Question?
Despite that making declaration volatile, don't change the answer of this question because static method and instance method still not synchronized each other.
1. Probably. You may have to go through JLS to understand why they designed it like this.
2. Volatile will ensure that the changes will be visible in another thread eventually. However, volatile does not guarantee the sequence of operations i.e. it cannot guarantee that one thread will block before other thread finishes the operation. For that, you need synchronization.
Paul - If the sum integer was changed to a static variable instead then the answer would still be the same (10 or 20 but not 0, correct? Since it is a static variable and resides on the heap just like an object it is still succeptible to the happens-before relationship and race conditions, right?
I tried to run the code to verify this but on my system I keep getting 20 regardless of whether the integer is static or not so I thought I would ask to ensure that my logic was correct. I also did not see anything about static variables in the happens-before article.
I am not sure I understand your question. When you synchronize a method (any method), it is only that method that is synchronized. If the method that is synchronized is static, then the lock used for synchronizing is the Class object of that class. If the method that is synchronized is an instance method, then the lock used for synchronizing is that particular instance.
I will suggest you to read this topic thoroughly from a book first before attempting questions on this topic.
public class StaticSyncTest {
static int sum = 0;
public synchronized void add(int x){
sum = sum + x;
}
public static synchronized void add(StaticSyncTest sst, int x){
sst.sum = sst.sum +x;
}
public static final StaticSyncTest sst = new StaticSyncTest();
public static void main(String[] args)throws Exception {
Thread t = new Thread(){
public void run(){
StaticSyncTest.add(sst, 10);
}
};
t.start();
sst.add(10);
t.join();
System.out.println(sst.sum);
}
}
I have studied the topic but after reading krohani's comment, I have this doubt suppose I changed the question's code just by a little to what krohani said ->
make the sum variable static. Now leave aside the output and join method here.
What if two different threads call one non static synchronized method and one static synchronized method at the same time just like it's happening in the question and suppose both these methods change the state of sum variable. Now my question is will both threads corrupt the value of the static variable or will one thread be only able to lock, change its state, release the lock and then let the other thread change the state of the variable?? I have this doubt because non static methods can directly access the static variables of the class. I hope you got my question. If not then I'll try to pin point the steps.
They will indeed corrupt the variable because the methods will be using different lock. static method will using the lock of the Class object while the instance method will use that lock of the instance. So both the threads will be able to access the static variable simultaneously and will corrupt it.
Thanks! I should have used code in the first place for asking my question.
One last thing suppose if this situation is encountered in an application
then what will be the best possible solution?
I guess changing the non-static method's code to this might be one?
public class StaticSyncTest {
static int sum = 0;
public synchronized void add(int x){
synchronized(StaticSyncTest.class)
{
sum = sum + x;
}
}
public static synchronized void add(StaticSyncTest sst, int x){
sst.sum = sst.sum +x;
}
Therefore, it is possible for the both threads to update sum simultaneously, which may cause one update to be lost. Thus, sum can be 10 or 20.
Having read both the happens-before documentation and this entire thread, I still cannot understand how an update can be lost.
I mean, even if both threads update sum simultaneously, what I expect is that a happens-before takes place and eventually both updates are executed.