java - 如果在同步块内完成简单的写入,那么在另一个同步块中的读取是一致的吗?
问题描述
一个线程写入变量的值,另一个线程读取它,以防两个操作都包含在同步块中,但都定义在不同的对象上,如下所示。
private Object o1 = new Object();
private Object o2 = new Object();
private int x = 0;
...
synchronized(o1){
x = 10;//write (simple atomic write) inside the synchronized block so value is flushed to main memory
}
...
synchronized(o2){
System.out.println(x);// read inside the synchronized block so read from main memory and not from thread cache.
}
Q1。是否保证 read 与 x 的最新值一致?
另一个案例
private Object a = new Object();
private Object b = new Object();
private int p = 0;
...
synchronized(a){
p = p + 1;
}
....
synchronized(b){
System.out.println(p);
}
Q2。由于 p = p+1
不是原子的,因此在这种情况下我们可能会出现数据不一致。但是对于第一季度。这种情况下,写入是简单且原子的,并且在同步块中完成,因此在这种情况下我们具有一致性。
如果我的理解正确,请帮助我。
解决方案
Q1。是否保证 read 与 x 的最新值一致?
不,因为它们在不同的事情上是同步的。
在同一监视器上同步块的结束和同步块的开始之间存在发生前的关系。
如果监视器不同,则不存在这种关系。
您可以在语言规范JLS 17.4.5(强调我的)中找到它:
从上面的定义可以得出:
- 监视器上的解锁发生在该监视器上的每个后续锁定之前。
- 对 volatile 字段(第 8.3.1.4 节)的写入发生在对该字段的每次后续读取之前。
- 线程上的 start() 调用发生在已启动线程中的任何操作之前。
- 线程中的所有操作都发生在任何其他线程从该线程上的 join() 成功返回之前。
- 任何对象的默认初始化发生在程序的任何其他操作(默认写入除外)之前。
Q2。由于 p = p+1 不是原子的,因此在这种情况下我们可能会出现数据不一致的情况。但是对于第一季度。这种情况下,写入是简单且原子的,并且在同步块中完成,因此在这种情况下我们具有一致性。
你没有一致性。请参阅 Q1 的答案。
推荐阅读
- javascript - Angular将值从下拉列表添加到列表中,从列表添加到下拉列表中
- autodesk-forge - Autodesk forge grey colour showing through colour material
- android - Room:如何获取成员的实际余额并将其用于setter方法来设置特定成员的余额
- javascript - padStart 有什么替代品
- tableau-api - Tableau 未显示分区字段(Athena Connection)
- java - 使用方法查询 spring boot thymeleaf 的搜索表
- git - 撤消将功能合并到开发中的 git flow 功能完成
- c++ - 如何在不缓存到数组的情况下对 0、1、...、n-1 中的 k 个随机数进行采样
- java - 将迭代器转换为流并调用并行,转换是在共享线程池线程上完成的吗?
- .htaccess - 从 HTTP 重定向到 HTTPS 显示公用文件夹