简体   繁体   中英

Java concurrency issue about visibility

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 ? Ie will every change inside the synchronized block be visible? Or should I change C object to volatile to make it change visible to others?

Making obj volatile will make the reference to the C object volatile . ie visible outside the synchronised block. It won't affect the members of that object.

ie a reassignment to obj will be visible to another thread. A reassignment to its members won't.

is every thing change inside the synchronized block will be visibile?

Yes that's the idea. The JLS 17.45 defines happens before relationships. In particular:

An unlock on a monitor happens-before every subsequent lock on that monitor.

So when thread2 acquires the lock, you have the guarantee that it will see the changes made by thread1 while holding that same lock.

Should I change C object to volatile to make it change visible to others?

volatile guarantees that if you write: obj = new C(); somewhere, a subsequent read of obj will 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 make x volatile too.

now the visibility is that all other thread will read the changes to obj ?

Only threads inside a synchronized block for that lock.

is every thing change inside the synchronized block will be visibile ?

Only probably. For guarenteed visibility the thread has to be inside a synchronized block.

or i should change C object to volatile ?

It will not help if you didn't have synchronized and will not make any difference here. volatile will only changes the behaviour of the obj reference, not it's fields.

No, accessing to obj fields is still not thread-safe. Synchronization on the lock object only allows you thread-safe operations for writing values to obj 's fields in this block.

UPD : volatile for obj will not help you, because you don't change this field's own reference value.

To answer your question, another method can simply give you access to the variable obj, without the lock too. What you have to ensure is that all accesses to obj must be guarded carefully through locks, so that obj is not in an inconsistent state (as defined by a programmer).

In your particular example, it looks consistent enough to me.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM