public class X implements Runnable { public volatile Object x = new Object(); @Runnable public void run() { for (;;) { Thread.sleep(1000); x = new Object(); } } }
x从另一个线程读取为null?
奖金:我需要声明它是波动的(我真的不在乎这个价值,只要在将来的某个时候,它将是新分配的值,从不是null)
解决方法
Reads value field of an entry under lock. Called if value field ever appears to be null. This is possible only if a compiler happens to reorder a HashEntry initialization with its table assignment,which is legal under memory model but is not known to ever occur.
由于HashEntry的价值是不稳定的,所以这种类型的重新排序是合法的.
故事的道德是,所有的非最终初始化都可以与对象构造竞争.
编辑:
@ Nathan Hughes问了一个有效的问题:
@John: in the OP’s example wouldn’t the construction have happened before the thread the runnable is passed into started? it would seem like that would impose a happens-before barrier subsequent to the field’s initialization.
Doug Lea对这个话题有几个评论,整个主题可以是read here.他回答了这个意见:
But the issue is whether assignment of the new C instance to some other memory must occur after the volatile stores.
有了答案
Sorry for mis-remembering why I had treated this issue as basically settled:
Unless a JVM always pre-zeros memory (which usually not a good option),then
even if not explicitly initialized,volatile fields must be zeroed
in the constructor body,with a release fence before publication.
And so even though there are cases in which the JMM does not
strictly require mechanics preventing publication reordering
in constructors of classes with volatile fields,the only good
implementation choices for JVMs are either to use non-volatile writes
with a trailing release fence,or to perform each volatile write
with full fencing. Either way,there is no reordering with publication.
Unfortunately,programmers cannot rely on a spec to guarantee
it,at least until the JMM is revised.
并完成了:
Programmers do not expect that even though final fields are specifically
publication-safe,volatile fields are not always so.For varIoUs implementation reasons,JVMs arrange that
volatile fields are publication safe anyway,at least in
cases we know about.Actually updating the JMM/JLS to mandate this is not easy
(no small tweak that I know applies). But now is a good time
to be considering a full revision for JDK9.In the mean time,it would make sense to further test and validate JVMs as meeting this likely future spec.