java.io.FileInputStream访问私有volatile变量' closed'仅来自同步块内部。为什么?

时间:2015-08-05 13:49:55

标签: java multithreading volatile happens-before

据我所知,'发生在之前'声明同步内部所做的更改对下一个线程可见,并在同一个锁上同步。

private final Object closeLock = new Object();
private volatile boolean closed = false;

public void close() throws IOException {
    synchronized (closeLock) {
        if (closed) {
            return;
        }
        closed = true;
    }
    if (channel != null) {
       channel.close();
    }

    fd.closeAll(new Closeable() {
        public void close() throws IOException {
           close0();
       }
    });
}

不是多余的吗?

3 个答案:

答案 0 :(得分:2)

同步在Java中提供了两种不同的保证:可见性和原子性。使变量volatile保证JVM将确保正确遵循“之前发生”的写入可见性,但不保证同步块中的check-then-act是原子的。

如果没有原子性保证,if (closed) return; closed = true;序列上的线程交错可能会导致一些同步问题。

如果始终从同一监视器上的同步块内访问变量,则volatile不是必需的,但可能会对性能产生轻微影响。

答案 1 :(得分:1)

该变量很可能由本机方法访问。您需要查看JDK的本机源代码。

答案 2 :(得分:1)

根据Memory Consistency Properties的第二个要点,volatile关键字是多余的。

  

监视器的解锁(同步块或方法退出)   发生在每个后续锁定之前(同步块或方法)   那个监视器的入口)。并且因为发生在关系之前   是传递的,解锁之前线程的所有动作   发生之前任何线程锁定之后的所有操作   监视。