Section 3.2.1 of Goetz\'s \"Java Concurrency in Practice\" contains the following rule:
Do not allow the
this
reference to escape during con
You are correct. In general, Java memory model does not treat constructors in any special way. Publishing an object reference before or after a constructor exit makes very little difference.
The only exception is, of course, regarding final
fields. The exit of a constructor where a final field is written to defines a "freeze" action on the field; if this
is published after the freeze
, even without happens-before edges, other threads will read the field properly initialized; but not if this
is published before the freeze
.
Interestingly, if there is constructor chaining, freeze
is defined on the smallest scope; e.g.
-- class Bar
final int x;
Bar(int x, int ignore)
{
this.x = x; // assign to final
} // [f] freeze action on this.x
public Bar(int x)
{
this(x, 0);
// [f] is reached!
leak(this);
}
Here leak(this)
is safe w.r.t. this.x
.
See my other answer for more details on final
fields.
If final
seems too complicated, it is. My advice is -- forget it! Do not ever rely on final
field semantics to publish unsafely. If you program is properly synchronized, you don't need to worry about final
fields or their delicate semantics. Unfortunately, the current climate is to push final
fields as much as possible, creating an undue pressure on programmers.