Search code examples
javamultithreadingvolatilehappens-before

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


As far as I know, 'happens-before' states that changes made inside synchronized are visible to next thread, synchronizing on the same lock.

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

Isn't it redundant?


Solution

  • Synchronization makes two different guarantees in Java: visibility and atomicity. Making the variable volatile guarantees that the JVM will ensure visibility of writes properly follow "happens-before", but does not guarantee that the check-then-act within the synchronized block is atomic.

    Without the guarantee of atomicity, thread interleaving on that sequence of if (closed) return; closed = true; could result in some synchronization issues.

    If the variable is always accessed from within synchronized blocks on the same monitor, the volatile is not necessary, but might have some other minor performance impact.