简体   繁体   English

JMM处于同步和易失状态

[英]JMM in synchronized and volatile

Many times I saw constructions like this one: 我多次看到这样的结构:

class OneTimeWriter {
    volatile Object o;

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

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

We have read/write membars at the begining/end of synchronized itself. synchronized本身的开始/结束时,我们已读取/写入成员。 So, can we remove volatile from o, since synchronized has release/acquire semantics itself? 那么,由于synchronized具有发布/获取语义本身,我们可以从o中除去volatile吗?

Not unless get is also synchronized ; 除非getsynchronized otherwise, there's no happens-before relationship between the setter putting something non- null into the field and the get call. 否则,在setter中将非null放入字段和get调用之间就没有事前发生的关系。

Synchronization isn't absolute; 同步不是绝对的。 it's always relative to another action. 它总是与另一个动作有关。 In the case of a synchronized block, the synchronization is between the closing of one synchronized block and the opening of a subsequent one on the same object. 对于synchronized块,同步是在同一对象上一个synchronized块的关闭与下一个synchronized块的打开之间。

Since your get method doesn't use synchronized , there is no happens-before relationship established between it and the set method. 由于您的get方法不使用synchronized ,因此它与set方法之间没有建立事前关系。 The getting thread could read a partially-set object put in by the setter, due to reorderings. 由于重新排序,获取线程可以读取设置器放置的部分设置的对象。 For instance, if you put in ("Foo", 123) , the getting thread could read that that same object as having state (null, 123) : the 123 state is there, but the "Foo" state hasn't yet been written (or flushed to this core's memory, etc). 例如,如果您放入("Foo", 123) ,则获取线程可以读取与具有状态(null, 123)相同的对象: 123状态存在,但"Foo"状态尚未存在写入(或刷新到该内核的内存等)。

Besides the synchronized block, another form of synchronization happens between the writing of a volatile field and the subsequent reading of that same field. synchronized块外,另一种形式的同步发生在volatile字段的写入与该字段的后续读取之间。 That — and only that — is what provides the happens-before relationship you need in this case. 在这种情况下,只有(这)才可以提供您需要的事前关系。 The synchronized block in the setter only makes sure that this.o isn't set twice, nothing more. 设置器中的synchronized块仅确保this.o未被设置两次,仅此而已。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM