Java内存模型中的部分构造对象
作者:互联网
我遇到了以下代码in an article somewhere on the Internet:
public class MyInt {
private int x;
public MyInt(int y) {
this.x = y;
}
public int getValue() {
return this.x;
}
}
文章指出
Constructors are not treated special by the compiler (JIT, CPU etc) so it is allowed to reorder instructions from the constructor and instructions that come after the constructor.
此外,关于Java内存模型的this JSR-133 article说明了这一点
A thread that can only see a reference to an object after that object has been completely initialized is guaranteed to see the correctly initialized values for that object’s final fields.
上面提到的MyInt实例似乎是不可变的(除了类没有标记为final)和线程安全,但文章声明它不是.他们声明不能保证x在读取时始终具有正确的值.
但我想到了
only the thread that creates an object should have access to it while it is being constructed
并且Java Tutorials看起来如此支持.
我的问题是:它是否意味着,使用当前的JMM,由于指令重新排序,线程可以访问部分构造的对象?如果是,怎么样?这是否意味着Java教程中的陈述根本不正确?
解决方法:
那篇文章说如果你有像这样的代码
foo = new MyInt(7);
在具有字段的类中
MyInt foo;
然后说明相当于
(reference to new object).x = 7;
foo = (reference to new object);
可以作为某种优化进行交换.这永远不会改变运行此代码的线程的行为,但是有些其他线程可能会在行之后读取foo
foo = (reference to new object);
但在排队之前
(reference to new object).x = 7;
在这种情况下,它会将foo.x视为0,而不是7.也就是说,其他线程可以运行
int bar = someObject.getFoo().getValue();
并以bar等于0结束.
我从来没有见过这样的事情发生在野外,但作者似乎知道他在说什么.
标签:java-memory-model,java,concurrency,final 来源: https://codeday.me/bug/20190823/1699278.html