Saturday, July 5, 2008

Synchronization of constructors not allowed in Java - why?

Synchronization of constructors not allowed in Java - why?

In Java, synchronization of contructors is not allowed (results in a compile time error) as only the thread which is constructing the object should have access to the object and hence any other thread is not granted access until the construction of the object is complete. So, no explicit synchronization needed for constructors.

Caution: even though other threads will be given the access to an object only when it's already constructed, but if the constructor itself is allowing a memory leak then an imcomplete object can also be accessed by other threads which is obviously undesirable as the behavior is undefined. This may happen in case we are maintaining a Collection of instances (say with the reference 'instances') of the class and if the constructor is using the statement 'instances.add(this);' to add the current instance to the Collection then a half-baked object may be accessed by other threads.

Read next - static method/field synchronization >> The article tries to answer these questions: How does the static method synchronization differ from instance method synchronization? How do we ensure exclusive access to static fields being accessed in synchronized instance methods?

Liked the article? You may like to Subscribe to this blog for regular updates. You may also like to follow the blog to manage the bookmark easily and to tell the world that you enjoy GeekExplains. You can find the 'Followers' widget in the rightmost sidebar.



Anonymous said...

So does this mean that the compiler internally synchronizes constructors and there is no need for us to explicitly synchronize it?

Geek said...

Well... would we ever need synchronization of a constructor? Evidently NO.

Synchronization of a method is required in a multi-threaded program to ensure that two or more threads don't call the method on the same object leaving the state inconsistent.

For constructors, we don't really have such a need as they are not called on an object. For them we just need an assurance that while one thread is still busy with creating the object, any other thread should not have access to the half-baked object and this is guaranteed by Java unless the constructor itself is flawed (as discussed in the article).

We can only speculate about how Java guarantees this, but apparently it doesn't require synchronization. It can maintain an info about whether an object has been fully created or not (maybe by polling for the value of some attribute - either the intrinsic 'lock' or some other attribute, which marks the completeness of an object) and that info can be used to deny any other thread access to an incomplete object.

When is this info/attribute set? Once the control exits the constructor OR before that? In a normal situation where constructor is just doing the initialization of the object, the info/attribute is probably set once the constructor finishes its execution (completion marked for a complete object). But, in a situation like the one discussed in article (under 'caution') where we are adding a half-baked instance to some collection from within the constructor body, the info/attribute probably gets set before the constructor finishes its execution (completion marked for an incomplete object) - probably because the collection allows only complete objects to be added and not the half-cooked ones.

This is why the behavior is undefined in such a situation as the object added to the collection only pretends to be a complete object, but it is actually not until the constructor in the first thread completes execution.

Does this make sense? BTW, these are my instant thoughts on the topic and might require a review. Open to suggestions/queries on this.

Unknown said...

I would like to add my understanding on such a nice article....
Each time a constuctor is called
for a object of different identity,
this reference will always be different in it.
evidently we should get a different hashcode in constructor(if it is not overridden).
If we tag a method as synchronized,then we are taking lock on that particular object
:-).A constructor always gets a different this reference on each invocation.Constructors and hence any thread calling constructor always works on distinct objects.
So no point of synchronization on constructors by java.If we pass some shared object to constructor,then we can use synchronized block on that shared object inside constructor.