1

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

class OneTimeWriter {
    volatile Object o;

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

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

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

4

2 回答 2

1

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

于 2014-03-28T03:30:17.950 回答
1

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

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

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

于 2014-03-28T03:35:08.240 回答