首页 > 解决方案 > 如果在同步块内完成简单的写入,那么在另一个同步块中的读取是一致的吗?

问题描述

一个线程写入变量的值,另一个线程读取它,以防两个操作都包含在同步块中,但都定义在不同的对象上,如下所示。

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不是原子的,因此在这种情况下我们可能会出现数据不一致。但是对于第一季度。这种情况下,写入是简单且原子的,并且在同步块中完成,因此在这种情况下我们具有一致性。

如果我的理解正确,请帮助我。

标签: javamultithreadingsynchronized

解决方案


Q1。是否保证 read 与 x 的最新值一致?

不,因为它们在不同的事情上是同步的。

在同一监视器上同步块的结束和同步块的开始之间存在发生前的关系。

如果监视器不同,则不存在这种关系。

您可以在语言规范JLS 17.4.5(强调我的)中找到它:

从上面的定义可以得出:

  • 监视器上的解锁发生在该监视器上的每个后续锁定之前。
  • 对 volatile 字段(第 8.3.1.4 节)的写入发生在对该字段的每次后续读取之前。
  • 线程上的 start() 调用发生在已启动线程中的任何操作之前。
  • 线程中的所有操作都发生在任何其他线程从该线程上的 join() 成功返回之前。
  • 任何对象的默认初始化发生在程序的任何其他操作(默认写入除外)之前。

Q2。由于 p = p+1 不是原子的,因此在这种情况下我们可能会出现数据不一致的情况。但是对于第一季度。这种情况下,写入是简单且原子的,并且在同步块中完成,因此在这种情况下我们具有一致性。

你没有一致性。请参阅 Q1 的答案。


推荐阅读