Java内存模型中的部分构造对象 [英] Partial constructed objects in the Java Memory Model

查看:66
本文介绍了Java内存模型中的部分构造对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在以下内容中遇到了以下代码互联网上某处的文章:

I came across the following code 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;
    }
}

文章指出

编译器(JIT,CPU等)不对构造函数进行特殊处理,因此可以对构造函数中的指令和构造函数之后的指令进行重新排序.

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.

此外,此JSR-133文章关于Java内存模型指出

Also, this JSR-133 article about the Java Memory Model states that

一个线程只有在完全初始化该对象之后才能看到对该对象的引用,这保证了该对象的最终字段可以看到正确初始化的值.

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在读取时始终具有正确的值.

The abovementioned MyInt instance seems immutable (except that the class is not marked final) and thread-safe, but the articles state it is not. They state that it's not guaranteed that x always has the correct value upon read.

但是我认为

只有创建对象的线程在构造对象时才可以访问它

only the thread that creates an object should have access to it while it is being constructed

Java教程似乎对此表示支持.

and the Java Tutorials seem so support that.

我的问题是:这是否意味着在当前的JMM中,由于指令重新排序,线程可以访问部分构造的对象?如果是的话,怎么办?这是否意味着Java教程中的陈述是不正确的?

My question is: does it mean that, with the current JMM, a thread can have access to a partially constructed object due to instruction reordering? And if yes, how? And does that mean that the statement from the Java Tutorials is simply not true?

推荐答案

该文章是说,如果您有类似的代码

That article is saying that if you have code like

foo = new MyInt(7);

在具有字段的类中

MyInt foo;

然后说明

(reference to new object).x = 7;
foo = (reference to new object);

可以作为某种优化交换.这将永远不会改变运行此代码的线程的行为,但是其他一些线程可能能够在该行之后读取foo

could be swapped over as some kind of optimisation. This will never change the behaviour of the thread that's running this code, but it's possible that some other thread will be able to read foo after the line

foo = (reference to new object);

但在该行之前

(reference to new object).x = 7;

在这种情况下,它将foo.x视为0,而不是7.也就是说,其他线程可以运行

in which case it would see foo.x as 0, not 7. That is to say, that other thread could run

int bar = someObject.getFoo().getValue();

并以bar等于0结束.

我从来没有见过这样的事情在野外发生,但是作者似乎知道他在说什么.

I've never seen anything like this happen in the wild, but the author seems to know what he's talking about.

这篇关于Java内存模型中的部分构造对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆