java - 同步块中的操作对其他线程可见吗?
问题描述
我已阅读此相关问题,答案对我有很大帮助,但仍有一个问题。
我听说同步块中共享字段的更改保证对其他线程可见。
对于这样的代码:
线程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 上的所有后续锁定操作同步(其中“后续”根据同步顺序定义)。
这表明解锁操作发生在后续锁定操作之前。但我找不到像这样的词:
同步块中的动作发生在解锁动作之前。
那么它是正确的吗?我在哪里可以找到它?
解决方案
同一个线程的所有动作都按照happens-before关系排序。
JLS 17.4.5:
如果 x 和 y 是同一线程的操作,并且 x 在程序顺序中位于 y 之前,则为 hb(x, y)。
另请注意,happens-before 是可传递的,因此如果同步块中的写入发生在解锁之前,并且解锁发生在另一个线程上的锁定之前,那么写入发生在另一个线程中同步块中的任何操作之前。
推荐阅读
- php - 将 MySQL 数据排序为限制大小的页面,并在屏幕上选择更改页面?它是如何完成的?
- javascript - 使用范围滑块和 JavaScript 更改 DiV 元素的宽度
- javascript - 只有五分之一的 div 转换正确
- tableau-api - 如何根据来自辅助混合数据源的条件过滤视图?
- php - 在 Laravel 请求中保留新行
- r - 如何在 R 中与另一列进行按列除法?
- python - 在 Windows 上为 Python 3.7 安装 pyodbc
- .htaccess - 如何防止机器人和蜘蛛消耗我的服务器资源?
- powerbi - 如何在 DAX Power BI 中按月细分日期范围?
- windows - 如何在不使用 Win32 API 激活窗口的情况下模拟按键组合