From the book Java Concurrency In Practice:
To publish an object safely, both the reference to the object and the object’s state must be made visible to other threads at the same time. A properly constructed object can be safely published by:
- Initializing an object reference from a static initializer;
- Storing a reference to it into a volatile field or AtomicReference;
- Storing a reference to it into a final field of a properly constructed object; or
- Storing a reference to it into a field that is properly guarded by a lock.
My question is:
Why does the bullet point 3 have the constrain:"of a properly constructed object", but the bullet point 2 does not have?
Does the following code safely publish the map
instance? I think the code meets the conditions of bullet point 2.
public class SafePublish {
volatile DummyMap map = new DummyMap();
SafePublish() throws InterruptedException {
new Thread(new Runnable() {
@Override
public void run() {
// Safe to use 'map'?
System.out.println(SafePublish.this.map);
}
}).start();
Thread.sleep(5000);
}
public static void main(String[] args) throws InterruptedException {
SafePublish safePublishInstance = new SafePublish();
}
public class DummyMap {
DummyMap() {
System.out.println("DummyClass constructing");
}
}
}
The following debug snapshot pic shows the map
instance is null
at the time of the execution is entering the construction of SafePublish
. What happens if another thread now trying to read the map
reference? Is it safe to read?