何时对同步块的更改对其他线程可见

dsa*_*ish 10 java synchronization

假设我在synchronized方法中更新了两个变量的值.退出synchronized块之前,同步方法中设置的新值是否可能对其他线程可见?

public synchronized void setValues(){
    a=5;
    // assume thread is preempted after this assignment
    // would the value 5 be visible to other threads?
    // my understanding is that the values will not be flushed to
    // main memory until the lock is released- i.e., until the synchronized
    // method is complete. So the changes will not be visible to other 
    // threads even when not using synchronization
    b=10;
}
Run Code Online (Sandbox Code Playgroud)

下面的方法同步,所以我理解该线程可能会 看到陈旧的值.我的问题是,如果线程在分配给a之后被抢占,那么变量a的新值"5"是否可能在printValues方法中可见?

public void printValues() {
    System.out.println(a + " " + b);
}
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 14

是的,在到达synchronized块的末尾之前,在synchronized can(但不保证)内进行的更改是可见的.基本上,您通常需要在读取写入数据时同步(在同一个锁上),以便获得一致的世界视图.

提供同步的保证是使"做正确的事"(适当地同步)正常工作-他们保证改变原子制成,当你没有做正确的事(观察共享变量不同步).

您可以(在某种程度上)将同步块内的写入视为与调用OutputStream.write()同步块的退出就像flush()调用一样.当你在块的一半时,你写的一些数据可能已经输出到输出文件(或其他任何东西) - 但它仍然可以被缓冲.这并不意味着如何实现内存模型,只是为了帮助您了解如何保证可见性.

  • @lexicore:不,它不能保证.内存模型不是根据"何时写入主存储器"来编写的 - 它是根据"先发生"和"同步"关系编写的. (3认同)
  • @Satish:基本上是 JLS 第 17.4 节的全部:http://java.sun.com/docs/books/jls/third_edition/html/memory.html#17.4特别是,“非正式地,允许读取 r如果没有“happens-before”命令来阻止读取,请查看写入 w 的结果。” 在您的情况下,没有发生之前来阻止“printValues”看到“a”的“新”值。 (2认同)