Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't Java constructors be synchronized?

According to the Java Language Specification, constructors cannot be marked synchronized because other threads cannot see the object being created until the thread creating it has finished it. This seems a bit odd, because I can indeed have another thread view the object while it's being constructed:

public class Test {     public Test() {        final Test me = this;        new Thread() {            @Override            public void run() {                // ... Reference 'me,' the object being constructed            }        }.start();     } } 

I know that this is a pretty contrived example, but it seems in theory that someone could come up with a more realistic case where marking the constructor synchronized would be legitimate in order to prevent races with threads like this one.

My question is this: is there a reason that Java would specifically disallow the synchronized modifier on a constructor? Perhaps my above example is flawed, or perhaps there really is no reason and it's an arbitrary design decision. In either case, I'm really curious and would love to know the answer.

like image 676
templatetypedef Avatar asked Feb 02 '11 21:02

templatetypedef


People also ask

Can we use synchronized constructor in Java?

No, a constructor cannot be synchronized in Java. The JVM ensures that only one thread can invoke a constructor call at a given point in time. That is why no need to declare a constructor as synchronized and it is illegal in Java.

Which constructor Cannot be used for process synchronization?

No, constructor cannot be synchronized. Because constructor is used for instantiating object, when we are in constructor object is under creation. So, until object is not instantiated it does not need any synchronization. Any attempt to do so is against java coding syntax.

What is the problem with synchronization in Java?

Synchronization can result in hold-wait deadlock where two threads each have the lock of an object, and are trying to acquire the lock of the other thread's object. Synchronization must also be global for a class, and an easy mistake to make is to forget to synchronize a method.

What is the disadvantage of synchronization in Java?

In simple two lines Disadvantage of synchronized methods in Java : Increase the waiting time of the thread. Create performance problem.


2 Answers

If you really need synchronization of the rest of the constructor versus any threads which anyhow gets a reference to your not-yet-totally-constructed object, you can use a synchronized-block:

public class Test {     public Test() {        final Test me = this;        synchronized(this) {           new Thread() {              @Override              public void run() {                 // ... Reference 'me,' the object being constructed                 synchronized(me) {                    // do something dangerous with 'me'.                 }              }           }.start();           // do something dangerous with this        }     } } 

Usually it is considered bad style to "give out" your not-yet-constructed object like this, so a synchronized constructor is not necessary.


In some corner cases a synchronized constructor would be useful. Here is a more realistic example, from the discussion of Bozho's answer:

public abstract class SuperClass {     public SuperClass() {        new Thread("evil") { public void run() {           doSomethingDangerous();        }}).start();        try {           Thread.sleep(5000);        }        catch(InterruptedException ex) { /* ignore */ }    }     public abstract void doSomethingDangerous();  }  public class SubClass extends SuperClass {     int number;     public SubClass () {         super();         number = 2;     }      public synchronized void doSomethingDangerous() {         if(number == 2) {             System.out.println("everything OK");         }         else {             System.out.println("we have a problem.");         }     }  } 

We want that the doSomethingDangerous() method is only called after construction of our SubClass object is complete, e.g. we only want the "everything OK" output. But in this case, when you only can edit your SubClass, you have no chance of achieving this. If the constructor could be synchronized, it would solve the problem.

So, what we learn about this: never do something like I did here in the superclass constructor, if your class is not final - and don't call any non-final methods of your own class from your constructor.

like image 111
Paŭlo Ebermann Avatar answered Sep 30 '22 15:09

Paŭlo Ebermann


The question has been raised on a discussion list used by the writers of the Java concurrent API and the Java Memory Model. Several answers were given, in particular Hans Boehm replied:

Some of us (myself included IIRC) actually argued during the Java memory model deliberations that synchronized constructors should be allowed. Now I could go either way on it. Client code shouldn't use races to communicate the reference, so it shouldn't matter. But if you don't trust the clients of [your class], I think synchronized constructors could possibly be useful. And that was much of the reasoning behind final field semantics. [...] As David said, you can use synchronized blocks.

like image 45
assylias Avatar answered Sep 30 '22 17:09

assylias