Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
529 views
in Technique[技术] by (71.8m points)

concurrency - Partial constructed objects in the Java Memory Model

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;
    }
}

The article states that

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.

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.

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.

But I thought that

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

and the Java Tutorials seem so support that.

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

That article is saying that if you have code like

foo = new MyInt(7);

in a class that has a field

MyInt foo;

then the instructions that amount to

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

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);

but before the line

(reference to new object).x = 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();

and end up with bar equal to 0.

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...