JMM在同步和易失性方面

时间:2014-03-28 03:28:41

标签: java java-memory-model

我多次看到像这样的结构:

class OneTimeWriter {
    volatile Object o;

    void synchronized set(Object o) {
        if(this.o == null) this.o = o;
    }

    Object get() {
        return this.o;
    }
}

我们在synchronized本身的开头/结尾处读/写膜。那么,我们可以从o中删除volatile,因为synchronized本身有释放/获取语义吗?

2 个答案:

答案 0 :(得分:1)

除非get也是synchronized,否则不会;否则,在设置者将非null放入字段和get调用之间的关系之前没有发生过。

答案 1 :(得分:1)

同步不是绝对的;它总是相对于另一个动作。对于synchronized块,同步是在一个synchronized块的关闭和同一对象上的后续块的打开之间。

由于您的get方法未使用synchronized,因此在它与set方法之间没有建立先发生关系。由于重新排序,获取线程可以读取由setter放入的部分设置对象。例如,如果您输入("Foo", 123),获取线程可以读取与具有状态(null, 123)相同的对象:123状态存在,但"Foo"状态没有还没写完(或冲到这个核心的记忆等)。

除了synchronized块之外,在写volatile字段和随后读取同一字段之间会发生另一种形式的同步。那个 - 而且只有那个 - 提供了在这种情况下你需要的事先发生的关系。设置器中的synchronized块仅确保this.o未设置两次,仅此而已。