1

据我所知,'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();
       }
    });
}

不是多余的吗?

4

3 回答 3

2

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

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

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

于 2015-08-05T13:57:40.377 回答
1

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

于 2015-08-05T14:21:43.900 回答
1

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

监视器的解锁(同步块或方法退出) 发生在同一监视器的每个后续锁定(同步块或方法入口)之前。并且由于happens-before关系是可传递的,因此线程在解锁 之前的所有动作都发生在任何线程锁定该监视器之后的所有动作之前。

于 2015-08-05T14:22:52.507 回答