Reputation: 1059
When synchronized block execution is completed all the processor cache is flushed or only that object on which synchronized statement acted on will be flushed? In the below example when thread finished execution of method2 does data of obj2 is also flushed to the main memory?
class cls1 {
int x=10;
}
class cls2{
int y=10;
}
class cls3{
cls1 obj1;
cls2 obj2;
public void method2(){
obj2.y=10;
synchronized(obj1){
obj1.x=30;
}
}
public static void main(String[] args) {
final cls3 obj3 = new cls3();
Thread thread1 = new Thread(){
public void run(){
obj3.method2();
}
};
Thread thread2 = new Thread(){
public void run(){
System.out.println(obj3.obj1.x);
}
};
}
}
Upvotes: 4
Views: 2605
Reputation: 116938
When synchronized block execution is completed all the processor cache is flushed or only that object on which synchronized statement acted on will be flushed?
Quick answer: all of the dirty blocks from the processor cache are flushed.
When a thread enters a synchronized
block, it crosses a read memory-barrier which causes local copies of memory that have been updated in main memory to be flushed from the local processor memory cache.
When a thread exits a synchronized
block, it crosses a write memory-barrier and all local processor dirty blocks are written to main memory. That's not just the lock object but all dirty memory blocks.
In the below example when thread finished execution of method2 does data of obj2 is also flushed to the main memory?
Yes. When the thread exits there is also a write memory barrier that is crossed.
System.out.println(obj3.obj1.x);
This probably will not print 30
. It is important to realize that:
thread2
will be running after thread1
completes. Even if you start thread2
after thread1
, race conditions may have the thread2
access of obj1
happen before thread1
updates it or flushes the cache to central memory.thread2
code does run after thread1
finishes, you will need to make sure that thread2
crosses a read memory barrier itself to read obj3
from main-memory and ensure that thread2
sees the memory updates from thread1
. That would mean making obj3
be volatile
or having thread2
also enter a synchronized
block.When you are sharing data between 2 threads it is necessary to make sure that you ensure proper order of operations and that the memory synchronization is taken into account.
Upvotes: 4
Reputation: 12006
JLS doesn't speak about caches and their coherence, it uses 'happens-before' relation to establish ordering of inter-thread actions such as reads and writes to a shared memory. In your example, it's permitted to re-order obj2.y=10
so it goes after sync
block. Plus, since there's no 'happens-before' established by method entry/exit, there's no guarantee from JMM that change will become visible after method finishes.
See "Java memory model" of Java spec for detailed explanation of underlying principles.
Btw, seems you forgot to call start()
method on thread instances you've created in main
.
Upvotes: 2
Reputation: 42005
A happens before relation is established only when the other thread also synchronizes on the lock using which the first thread updated the contents.
In this example Thread B after acquiring the lock on same object M, it will be able to see all the changes that were made before and during the synchronized block. But mind that the lock must be acquired for happens-before relationship to occur.
In your example because System.out.println(obj3.obj1.x);
is not printed inside a synchronized block, it does not guarantee happens before.
References:
EDIT: Excellent answer by Peter What is the scope of memory flushed or published to various threads when using volatile and synchronized?
Upvotes: 7