首页 > 解决方案 > 同步块中的操作对其他线程可见吗?

问题描述

我已阅读此相关问题,答案对我有很大帮助,但仍有一个问题。

我听说同步块中共享字段的更改保证对其他线程可见。

对于这样的代码:

线程1:

synchronized(lock) {
   obj.field1 = value1;
}

线程2:

synchronized(lock) {
   System.out.println(obj.field1);
}

假设 thread1 在 thread2 之前,据说根据 Java 规范,它可能是这样的:

hb(write to obj.field1 in threadOne, unlock in threadOne) AND 
hb(unlock in threadOne, lock in threadTwo) AND 
hb(lock in threadTwo, read from obj.field in threadTwo)

hb 在 Java 规范中代表happens-before,它保证了可见性。

并且因为“如果 hb(x, y) 和 hb(y, z), 那么 hb(x, z) ”,我们得到:

hb(write to obj.field1 in threadOne, read from obj.field1 in threadTwo) 

我的问题在第一行:

hb(write to obj.field1 in threadOne, unlock in threadOne) 

在 Java 规范中,我只发现:

监视器 m 上的解锁操作与 m 上的所有后续锁定操作同步(其中“后续”根据同步顺序定义)。

这表明解锁操作发生在后续锁定操作之前。但我找不到像这样的词:

同步块中的动作发生在解锁动作之前。

那么它是正确的吗?我在哪里可以找到它?

标签: javamultithreadingconcurrencysynchronized

解决方案


同一个线程的所有动作都按照happens-before关系排序。

JLS 17.4.5:

如果 x 和 y 是同一线程的操作,并且 x 在程序顺序中位于 y 之前,则为 hb(x, y)。

另请注意,happens-before 是可传递的,因此如果同步块中的写入发生在解锁之前,并且解锁发生在另一个线程上的锁定之前,那么写入发生在另一个线程中同步块中的任何操作之前。


推荐阅读