【问题标题】:synchronize on different object visibility同步不同的对象可见性
【发布时间】:2018-10-13 15:05:12
【问题描述】:

以下代码显示了与此不同的对象上的同步:

public class A {

int a,b,c,d;

public void method1(Object x){
   synchronized(x){
     // is a ,b ,c ,d guarantee visibility ? 
   }
}

   public synchronized void method2() {
        a++;
    }
}

我知道编辑 a 、 b 、 c 、 d 会出现问题,因为在 method1 和 method2 中有不同的锁定,但问题是 method2 刷新的更改对 method1 是可见的吗?因为他们不使用相同的锁。

【问题讨论】:

    标签: java multithreading synchronized volatile


    【解决方案1】:

    如果您只阅读a,在 x64 上这将发生,因为内存屏障不限于特定的内存位置。但是,我的理解是 Java 不保证这将是线程安全的,因为锁适用于不同的对象。当然,如果你在第一种方法中增加a,它就不是线程安全的。

    【讨论】:

    • 从你的回答我明白这句话是真的吧? “线程内存刷新其所有变量,即它的所有变量都有效地从“主”内存中读取。” ,即使 x 将从主存储器中读取? (我知道 x 是一个对象,应该在堆中,但这是否会强制任何同步块从主内存中读取每个变量?)
    • @MohammadKarmi 出于性能原因,内核的 L2 缓存在它们之间传递最新值,因此该值不必转到 L3 或主内存。
    • 了解一切的最后一个问题。假设method2在method1的同一个x对象上同步,在method1中的x,a,b,c,d的可见性会得到保证吗?
    • @MohammadKarmi 是的。
    【解决方案2】:

    我知道编辑 a 、 b 、 c 、 d 会出现问题,因为在 method1 和 method2 中具有不同的锁定,但问题是 method2 刷新的更改对 method1 是可见的吗?因为他们不使用相同的锁。

    在没有任何其他同步的情况下,Java 不保证在一个线程中通过A.method2()A.a 执行的修改是否或何时对A.method1() 可见,无论是在synchronized 块内部还是外部,在一个不同的线程。出现该问题的程序未正确同步,因此其行为未定义。

    【讨论】:

    • 假设 method2 在同一个 x 对象上同步(不是 this )是否能保证 x ,a,b,c,d 的可见性?
    • 如果method2 包含一个同步块,那么在执行该块在某个对象o1 上同步该块的方法时,该块内的代码将观察之前由该块执行的任何写入或在同一对象o1 上同步的任何其他块。同样,当o1A.method1() 的参数时,该方法的同步块中的代码将观察该方法或任何其他同步块在同一o1 上执行的任何写入,包括method2() 中的写入。
    • @MohammadKarmi,在同一个对象上同步进一步意味着一个同步块的执行总是在另一个同步块的执行之前或之后,尽管它没有说明哪个先执行。这具有进一步的含义,远远超出了两次处决不重叠的事实。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-19
    • 2022-08-16
    • 2017-03-18
    • 1970-01-01
    • 2018-09-23
    相关资源
    最近更新 更多