Directly from this web site, I came across the following description about creating object thread safety.
Warning: When constructing an object that will be shared between threads, be very careful that a reference to the object does not "leak" prematurely. For example, suppose you want to maintain a List called instances containing every instance of class. You might be tempted to add the following line to your constructor:
instances.add(this);
But then other threads can use instances to access the object before construction of the object is complete.
Is anybody able to express the same concept with other words or another more graspable example?
Thanks in advance.
Lot of good data here but I thought I'd add some more information.
While you are constructing the object, you need to make sure that there is no way for other threads to access this object before it can be fulling constructed. This means that in a constructor you should not, for example:
static
field on the class that is accessible by other threads.So something like the following is improper:
One addition bit of complexity is that the Java compiler/optimizer has the ability to reorder the instructions inside of the constructor so they happen at a later time. This means that even if you do
instances.add(this);
as the last line of the constructor, this is not enough to ensure that the constructor really has finished.If multiple threads are going to be accessing this published object, it must be
synchronized
. The only fields you don't need to worry about arefinal
fields which are guaranteed to be finished constructing when the constructor finishes.volatile
fields are themselves synchronized so you don't have to worry about them.As the thread scheduler can stop execution of a thread at any time (even half-way through a high level instruction like
instances.push_back(this)
) and switch to executing a different thread, unexpected behaviour can happen if you don't synchronize parallel access to objects.Look at the code below:
As the access to
a
inmain()
-function is not synchronized execution will fail every once in a while.This happens when execution of thread
t1
is halted before finishing construction of the objectA
and threadt2
is executed instead. This results in threadt2
trying to access aunique_ptr<A>
containing anullptr
.Let us assume, you have such class:
and you have two threads (thread #1 and thread #2), both of them have a reference the same
List<Sync> list
instance.Now thread #1 creates a new
Sync
instance and as an argument provides a reference to thelist
instance:While executing line
// switch
in theSync
constructor there is a context switch and now thread #2 is working.Thread #2 executes such code:
Thread #2 calls
bang()
on the instance created in point 3, but this instance is not ready to be used yet, because the constructor of this instance has not been finished.Therefore,
Its describing the following situation:
Here is your clear example :
Let's say, there is class named
House
And Village:
Now if you are creating a
House
in a thread, "X". And when the executing thread is just finished the bellow line,And the context is switched (already the reference of this object is added in the list
listOfHouse
, while the object creation is not finished yet) to another thread, "Y" running,in it! then
printHouses()
will see an object which is still not fully created and this type of inconsistency is known asLeak
.You just have to make sure, that even, when one thread hasn't initialized the Object, no Thread will access it (and get a NullpointerException).
In this case, it would happen in the constructor (I suppose), but another thread could access that very object between its add to the list and the end of the constructor.