java.io.FileInputStream 仅从同步块内部访问私有易失性变量 'closed'。为什么?

java.io.FileInputStream accesses private volatile variable 'closed' only from inside synchronized block. Why?

据我所知,'happens-before' 声明在 synchronized 内部所做的更改对下一个线程可见,在同一个锁上同步。

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();
       }
    });
}

这不是多余的吗?

同步在 Java 中提供两种不同的保证:可见性和原子性。使变量 volatile 保证 JVM 将确保写入的可见性正确遵循 "happens-before",但不保证同步块中的先检查后操作是原子的。

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

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

本机方法可能会访问该变量。您需要查看 JDK.

的本机源代码

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

An unlock (synchronized block or method exit) of a monitor happens-before every subsequent lock (synchronized block or method entry) of that same monitor. And because the happens-before relation is transitive, all actions of a thread prior to unlocking happen-before all actions subsequent to any thread locking that monitor.