首页 > 解决方案 > 在对象 Y 上定义的同步块中访问对象 X 是否安全?

问题描述

如果在同步方法或块中访问对象的状态是安全的,那么这个问题就有了答案。我的问题:在同步块中访问对象 X 是否安全,其中同步块位于另一个对象 Y 上,并且 X 存在多个编写者线程?

public class X{
    private int value = 0;
    /** set method will be invoked by multiple threads**/
    public void set(int v){
       this.value = v;
   }
   public int value(){
       return value;
   }
}

public class Tester{
    private final Object Y = new Object();
    public void test(X x){
        synchronized(Y){
            System.out.println(x.value()); // is it guaranteed that x.value will be read from memory and not from the current thread's cache ?
        }
    }
}      

我知道在其上定义了同步块的对象的状态是可以安全访问的,不需要 volatile,但是如果同步块是在另一个对象上定义的呢?

标签: javamultithreadingsynchronizedvolatile

解决方案


海事组织你问错了问题。Java 内存模型不关心对象和类。它只谈论变量的可见性。

块的可见性规则synchronized(o)非常简单:一个线程在离开块之前对任何变量所做的任何事情都保证在另一个线程随后进入同一实例上的synchronized(o)块之后对任何其他线程都是可见的。synchronizedo

所以,在你的例子中,如果你有一些X my_x,并且一些线程 A 这样做:

synchronized(Y) {
    my_x.set(55);
}

然后当其他线程 B 随后调用tester.test(my_x)时,线程 B 将看到线程 A 存储的值。

另一方面,如果线程 A在my_x.set(...) 没有同步 on的情况下调用Y,那么 Java 不会承诺线程 B 何时会看到更改。


注意:您的程序通过使锁对象成为类Yprivate成员Tester,同时使test(X)函数public. 这实际上是在请求您(或其他一些程序员)犯错误,即调用由另一个锁定的线程设置的tester.test(some_random_X)位置。some_random_XY


推荐阅读