I read that the synchronized method or block provides two features: “mutual exclusion” and “visibility”. I want to know two things.
public class A{
private final Object lock = new Object();
private C obj = new C();
public void methodA(){
synchronized(lock){
obj.x = 1;
obj.y=3;
}
}
public void methodB(C obj2){
synchronized(lock){
obj2.x = obj.x;
}
}
}
Let’s assume that we have 2 threads that called methodA on a global shared object of type A , and the lock is acquired by thread1 , now after thread1 release the lock . now the visibility is that all other thread will read the changes to obj? I.e. will every change inside the synchronized block be visible? Or should I change C object to volatile to make it change visible to others?
Yes that’s the idea. The JLS 17.45 defines happens before relationships. In particular:
So when thread2 acquires the lock, you have the guarantee that it will see the changes made by thread1 while holding that same lock.
volatile guarantees that if you write:
obj = new C();somewhere, a subsequent read ofobjwill see that it now refers to a new object. However, it does not provide any such guarantee with regards to the “content” of obj. So if you write:obj.x = someValue;, with obj being volatile, you don’t have a guarantee that the change will be visible to another thread. Unless you makexvolatile too.