How private constructors achieve publication safety in Java - java

In the classic "Java concurrency in Practice" Brian Goetz uses the following snippet of code to demonstrate how to safely publish an object using a private constructor and a factory method:
public class SafeListener {
private final EventListener listener;
private SafeListener() {
listener = new EventListener() {
public void onEvent(Event e) {
doSomething(e);
}
};
}
public static SafeListener newInstance(EventSource source) {
SafeListener safe = new SafeListener();
source.registerListener(safe.listener);
return safe;
}
}
What I can't figure out yet is how this code achieves safe publication through a private constructor.
I am aware that a private constructor is used to prevent instantiation outside of the object but how does that apply to a thread rather than an object? A thread is not necessarily an object and I can't see what stops another thread from acquiring a reference to safe before the constructor finishes execution.

The constructor’s property of being private has nothing to do with the thread-safety. This is an example of the final field publication guaranty. In order for it to work, the this instance of the final field must not escape during the constructor, therefore the factory method takes care of constructing the holder instance first and registering the listener afterwards. It’s natural for applications of the factory pattern to have private constructors and public factory methods but that is not important to achieve the thread-safety here.
It’s all about how JIT and the HotSpot optimizer treat the code when performing the optimizations. They know what final or volatile fields are and what a constructor is. They will obey the limitations to the degree of optimization of such constructs. Most important, they ensure that all writes to an object you store in the final field and the write to the final field itself happen-before the constructor ends so that the final field stores happen-before any effect of the registerListener invocation in your example. Therefore, other threads can’t see the listener reference before its correct initialization.
Note that this is something you should rarely rely on. In your example, if the method registerListener of the EventSource is not thread-safe, still very bad things can happen. On the other hand, if it’s thread-safe, its thread-safety will apply to the listener constructed before the registration as well so the final field guaranty would not be needed.

Point here is to prevent escapement of this till constructor is finished. To this end, constructor is made private and factory method is provided which takes care of registering listener in external code, after object's constructor finished.
An example of thread-safe API.

how does that apply to a thread rather than an object? A thread is not necessarily an object and I can't see what stops another thread from acquiring a reference to safe before the constructor finishes execution.
A Thread is always an object in the java.lang.Thread sense, of course. The pattern should not be applied to a thread itself. Instead, it could be applied for cases where a new Thread has to be started "together" with the construction of an object. Starting the thread IN the constructor can allow the reference to the incompletely constructed object to escape. However, with this pattern, the newly constructed instance is trapped in the newInstance method until its construction is entirely complete.
(Or to put it that way: I can't imagine how another thread should acquire a reference to the safe instance before its construction is complete. Maybe you can give an example how how you think this might happen.)

Related

Which way should I choose to make the class thread safe?

I have a code which is as below
class classA {
int sum = 0;
void recursiveMethodA {
sum = sum +1; // For simplicity
}
}
Basically I am doing some operation in a recursive method which runs lets say 10 times and changing state at class level. But this class is not thread safe.
Now in order to make it thread safe I am thinking of a below option.
class class B {
// Public exposed method
public void methodB {
ClassA classA = new ClassA();
classA.recursiveMethodA();
}
}
My logic is that since I am creating object of class A inside a method of class B, it is created on stack instead of heap and hence it is thread safe.
Is this logic correct? Please suggest alternate options.
My logic is that since I am creating object of class A inside a method of class B, it is created on stack instead of heap and hence it is thread safe.
Your logic and/or terminology are not correct. In fact, the instance of ClassA is in the heap. All regular Java objects are created in the heap!
Your code is actually thread-safe, but the correct explanation is as follows:
The object is created, and the only reference to it is assigned to a local variable.
By inspection, no other thread can ever see that variable.
By inspection, the object reference is never passed to another thread; i.e. it is not published.
The points 1., 2., and 3. mean that the object is thread confined1 for its entire lifetime.
Since the object is thread confined, it is not necessary to consider thread-safety.
It is not sufficient to say (just) that a local variable is used:
There are scenarios where another thread can see the value of a local variable; e.g. if a lambda or inner method closure is created and passed to another thread.
It is also necessary to consider that the value in the variable could be passed to another thread.
Finalization and reference processing will be done on another thread. However, this should NOT present a thread-safety concern. (The JLS spec takes care of finalization, and the javadocs for Reference take care of references. In both cases, there is a happens before at the appropriate points.)
1 - This is a fancy way of saying that no other thread can ever see it the object and its reference.
Do you mean classA is thread safe by itself?
No. It is not thread safe by itself. It is thread safe in this particular context. Or more to the point, thread safety is moot in this context ... because the instance is thread confined.
Shouldn't I define the class as thread safe in all the contexts? I don't know how tomorrow it can be used?
That is up to you!
But consider this: a large number of standard Java classes are NOT thread-safe ... by design. Indeed the classic case is StringBuilder which is the non-thread-safe reimplementation of StringBuffer. Others are most of the collection types in java.util!
Basically, you have two choices:
Make a class inherently thread-safe, and accept that this comes with runtime overheads.
Make a class inherently non-thread-safe, and make sure that you only use it ways that deal with this appropriately. (One way is to thread confine the instances. Another is to use some form of external synchronization.)
The simplest way to have a threadsafe function is put keyword "synchronized"
synchronized public void method() {
//do something
}

Why is an object not immutable if the "this" reference can escape during construction? [duplicate]

Goetz's Java Concurrency in Practice, page 41, mentions how this reference can escape during construction. A "don't do this" example:
public class ThisEscape {
public ThisEscape(EventSource source) {
source.registerListener(
new EventListener() {
public void onEvent(Event e) {
doSomething(e);
}
});
}
}
Here this is "escaping" via the fact that doSomething(e) refers to the enclosing ThisEscape instance. The situation can be fixed by using static factory methods (first construct the plain object, then register the listener) instead of public constructors (doing all the work). The book goes on:
Publishing an object from within its constructor can publish an incompletely constructed object. This is true even if the publication is the last statement in the constructor. If the this reference escapes during construction, the object is considered not properly constructed.
I don't quite get this. If the publication is the last statement in the constructor, hasn't all the constructing work been done before that? How come is this not valid by then? Apparently there's some voodoo going on after that, but what?
The end of a constructor is a special place in terms of concurrency, with respect to final fields. From section 17.5 of the Java Language Specification:
An object is considered to be
completely initialized when its
constructor finishes. 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 usage model for final fields is a
simple one. Set the final fields for
an object in that object's
constructor. Do not write a reference
to the object being constructed in a
place where another thread can see it
before the object's constructor is
finished. If this is followed, then
when the object is seen by another
thread, that thread will always see
the correctly constructed version of
that object's final fields. It will
also see versions of any object or
array referenced by those final fields
that are at least as up-to-date as the
final fields are.
In other words, your listener could end up seeing final fields with their default values if it examines the object in another thread. This wouldn't happen if listener registration happened after the constructor has completed.
In terms of what's going on, I suspect there's an implicit memory barrier at the very end of a constructor, making sure that all threads "see" the new data; without that memory barrier having been applied, there could be problems.
Another problem arises when you subclass ThisEscape, and the child class invokes this consructor. The implicit this reference in the EventListener would have an incompletely constructed object.
There is a small but finite time between the registerListener ending and the constructor returning. Another thread could use come in at that time and attempt to call doSomething(). If the runtime didn't return straight to your code at that time, the object could be in a invalid state.
I'm not sure of java really but one example I can think of is where possibly the runtime relocates the instance before returning to you.
Its a small chance I grant you.

Constructor synchronization in Java

Someone somewhere told me that Java constructors are synchronized so that it can't be accessed concurrently during construction, and I was wondering: if I have a constructor that stores the object in a map, and another thread retrieves it from that map before its construction is finished, will that thread block until the constructor completes?
Let me demonstrate with some code:
public class Test {
private static final Map<Integer, Test> testsById =
Collections.synchronizedMap(new HashMap<>());
private static final AtomicInteger atomicIdGenerator = new AtomicInteger();
private final int id;
public Test() {
this.id = atomicIdGenerator.getAndIncrement();
testsById.put(this.id, this);
// Some lengthy operation to fully initialize this object
}
public static Test getTestById(int id) {
return testsById.get(id);
}
}
Assume that put/get are the only operations on the map, so I won't get CME's via something like iteration, and try to ignore other obvious flaws here.
What I want to know is if another thread (that's not the one constructing the object, obviously) tries to access the object using getTestById and calling something on it, will it block? In other words:
Test test = getTestById(someId);
test.doSomething(); // Does this line block until the constructor is done?
I'm just trying to clarify how far the constructor synchronization goes in Java and if code like this would be problematic. I've seen code like this recently that did this instead of using a static factory method, and I was wondering just how dangerous (or safe) this is in a multi-threaded system.
Someone somewhere told me that Java constructors are synchronized so that it can't be accessed concurrently during construction
This is certainly not the case. There is no implied synchronization with constructors. Not only can multiple constructors happen at the same time but you can get concurrency issues by, for example, forking a thread inside of a constructor with a reference to the this being constructed.
if I have a constructor that stores the object in a map, and another thread retrieves it from that map before its construction is finished, will that thread block until the constructor completes?
No it won't.
The big problem with constructors in threaded applications is that the compiler has the permission, under the Java memory model, to reorder the operations inside of the constructor so they take place after (of all things) the object reference is created and the constructor finishes. final fields will be guaranteed to be fully initialized by the time the constructor finishes but not other "normal" fields.
In your case, since you are putting your Test into the synchronized-map and then continuing to do initialization, as #Tim mentioned, this will allow other threads to get ahold of the object in a possibly semi-initialized state. One solution would be to use a static method to create your object:
private Test() {
this.id = atomicIdGenerator.getAndIncrement();
// Some lengthy operation to fully initialize this object
}
public static Test createTest() {
Test test = new Test();
// this put to a synchronized map forces a happens-before of Test constructor
testsById.put(test.id, test);
return test;
}
My example code works since you are dealing with a synchronized-map, which makes a call to synchronized which ensures that the Test constructor has completed and has been memory synchronized.
The big problems in your example is both the "happens before" guarantee (the constructor may not finish before Test is put into the map) and memory synchronization (the constructing thread and the get-ing thread may see different memory for the Test instance). If you move the put outside of the constructor then both are handled by the synchronized-map. It doesn't matter what object it is synchronized on to guarantee that the constructor has finished before it was put into the map and the memory has been synchronized.
I believe that if you called testsById.put(this.id, this); at the very end of your constructor, you may in practice be okay however this is not good form and at the least would need careful commenting/documentation. This would not solve the problem if the class was subclassed and initialization was done in the subclass after the super(). The static solution I showed is a better pattern.
Someone somewhere told me that Java constructors are synchronized
'Somebody somewhere' is seriously misinformed. Constructors are not synchronized. Proof:
public class A
{
public A() throws InterruptedException
{
wait();
}
public static void main(String[] args) throws Exception
{
A a = new A();
}
}
This code throws java.lang.IllegalMonitorStateException at the wait() call. If there was synchronization in effect, it wouldn't.
It doesn't even make sense. There is no need for them to be synchronized. A constructor can only be invoked after a new(), and by definition each invocation of new() returns a different value. So there is zero possibility of a constructor being invoked by two threads simultaneously with the same value of this. So there is no need for synchronization of constructors.
if I have a constructor that stores the object in a map, and another thread retrieves it from that map before its construction is finished, will that thread block until the constructor completes?
No. Why would it do that? Who's going to block it? Letting 'this' escape from a constructor like that is poor practice: it allows other threads to access an object that is still under construction.
You've been misinformed. What you describe is actually referred to as improper publication and discussed at length in the Java Concurrency In Practice book.
So yes, it will be possible for another thread to obtain a reference to your object and begin trying to use it before it is finished initializing. But wait, it gets worse consider this answer: https://stackoverflow.com/a/2624784/122207 ... basically there can be a reordering of reference assignment and constructor completion. In the example referenced, one thread can assign h = new Holder(i) and another thread call h.assertSanity() on the new instance with timing just right to get two different values for the n member that is assigned in Holder's constructor.
constructors are just like other methods, there's no additional synchronization (except for handling final fields).
the code would work if this is published later
public Test()
{
// Some lengthy operation to fully initialize this object
this.id = atomicIdGenerator.getAndIncrement();
testsById.put(this.id, this);
}
Although this question is answered but the code pasted in question doesn't follow safe construction techniques as it allows this reference to escape from constructor , I would like to share a beautiful explanation presented by Brian Goetz in the article: "Java theory and practice: Safe construction techniques" at the IBM developerWorks website.
It's unsafe. There are no additional synchronization in JVM. You can do something like this:
public class Test {
private final Object lock = new Object();
public Test() {
synchronized (lock) {
// your improper object reference publication
// long initialization
}
}
public void doSomething() {
synchronized (lock) {
// do something
}
}
}

Static Instance Thread Safe

I have a strategy pattern implementation as below:
public class ConcreteStrategy implements Strategy {
public static final Strategy INSTANCE = new ConcreteStrategy();
public AClass execute(AClass aClass){
//...do somthing
return aClass;
}
}
Ignoring the bad practice of returning the input parameter, is static instance INSTANCE use thread safe?
Assuming ConcreteStrategy isn't modified, or is modified only in a thread-safe way, then yes. The final modifier will ensure (in Java 1.5+) that all threads see the INSTANCE object in at least the state it was in when the class was initialized. Any subsequent change to the object would need to be made thread-safe in the usual way (through volatiles, synchronization, classes that provide thread-safety, etc).
Generally any Object in java that is immutable or stateless is Thread-safe.
Your example is almost thread safe.
The reference to INSTANCE is thread-safe, since it's final. But the contents of the ConcreteStrategy might be very well not Thread safe (we do not see the code, thus can't tell).
If you provide proper synchronization to the ConcreteStrategy Object, then it could be very well a Thread safe Object.
Cheers, Eugene.

What is an "incompletely constructed object"?

Goetz's Java Concurrency in Practice, page 41, mentions how this reference can escape during construction. A "don't do this" example:
public class ThisEscape {
public ThisEscape(EventSource source) {
source.registerListener(
new EventListener() {
public void onEvent(Event e) {
doSomething(e);
}
});
}
}
Here this is "escaping" via the fact that doSomething(e) refers to the enclosing ThisEscape instance. The situation can be fixed by using static factory methods (first construct the plain object, then register the listener) instead of public constructors (doing all the work). The book goes on:
Publishing an object from within its constructor can publish an incompletely constructed object. This is true even if the publication is the last statement in the constructor. If the this reference escapes during construction, the object is considered not properly constructed.
I don't quite get this. If the publication is the last statement in the constructor, hasn't all the constructing work been done before that? How come is this not valid by then? Apparently there's some voodoo going on after that, but what?
The end of a constructor is a special place in terms of concurrency, with respect to final fields. From section 17.5 of the Java Language Specification:
An object is considered to be
completely initialized when its
constructor finishes. 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 usage model for final fields is a
simple one. Set the final fields for
an object in that object's
constructor. Do not write a reference
to the object being constructed in a
place where another thread can see it
before the object's constructor is
finished. If this is followed, then
when the object is seen by another
thread, that thread will always see
the correctly constructed version of
that object's final fields. It will
also see versions of any object or
array referenced by those final fields
that are at least as up-to-date as the
final fields are.
In other words, your listener could end up seeing final fields with their default values if it examines the object in another thread. This wouldn't happen if listener registration happened after the constructor has completed.
In terms of what's going on, I suspect there's an implicit memory barrier at the very end of a constructor, making sure that all threads "see" the new data; without that memory barrier having been applied, there could be problems.
Another problem arises when you subclass ThisEscape, and the child class invokes this consructor. The implicit this reference in the EventListener would have an incompletely constructed object.
There is a small but finite time between the registerListener ending and the constructor returning. Another thread could use come in at that time and attempt to call doSomething(). If the runtime didn't return straight to your code at that time, the object could be in a invalid state.
I'm not sure of java really but one example I can think of is where possibly the runtime relocates the instance before returning to you.
Its a small chance I grant you.

Categories

Resources