What is the use of synchronized block inside constructor?
Asked Answered
I

7

8

We can not make constructor synchronized but can write synchronized this inside constructor. In what case such requirement will come ? I am amused.

package com.simple;
public class Test {
    public Test() {
        synchronized (this) {
            System.out.println("I am called ...");
        }
    }

    public static void main(String[] args) {
        Test test=new Test();   
        System.out.println(""+test);
    }

    @Override
    public String toString() {
        return "Test []";
    }
}
Institutionalize answered 22/2, 2013 at 10:15 Comment(0)
R
10

Well, you could start a new thread within the constructor. It would be highly unusual - and certainly in the code you've provided it would be pointless - but it could happen.

Languages don't typically try to find every possibly thing you could do that would be pointless - it would lead to a very complex language specification. There has to be some degree of thought on the part of the language users, too...

Rosanarosane answered 22/2, 2013 at 10:17 Comment(2)
Let me ask you a question. For instance, we need to publish a thread-safe object safely from a constructor, say, like in this example. Is it safe to do so? I mean, does using synchronized(this) block within a constructor allow this object to escape or something...?Mccarter
@St.Antario: I don't see how that is publishing an object within a constructor. It's creating it, but nothing else can see the object until after the constructor has finished. It sounds like you may want to ask a new question though.Rosanarosane
H
6

Synchronizing on this would be a sign of bad practice because it would imply you are leaking this out of the constructor: this is the only way you could have some other code synchronizing on the same object.

Synchronizing on some other common lock, however, could be legitimate: the constructor my indeed involve calling some code that requires such synchronization.

Heaume answered 22/2, 2013 at 10:18 Comment(2)
Very interesting point. Coulnd't you explain the leak? I don't see how synchronized(this) within a contructor allows this to escape. Example: ideone.com/E6DCMm . Where is the escape here?Mccarter
@Mccarter He is saying that the only reason for having synchornized(this) is a leak. But I don't think that's always true, because synchronized can also be used to create a happens-before relationship with something that happens in another thread after the constructor is finished. See my answer to this question.Undoing
U
1

It could be used to ensure safe publication of non-final fields in the constructor.

public class Test {
    int a;
    public Test() {
        synchronized (this) {
            a = 5;
        }
    }

If another thread receives an object of type Test, and it also synchronizes on that instance of Test, then this creates a happens-before relation between the end of the synchronized block in the constructor, and the beginning of the synchronized block in the other thread:

public class InOneThread {
    public void run() {
        InAnotherThread.test = new Test();
    }
}

public class InAnotherThread {
     public static Test test;

     public void run() {
         if (test == null) {
             // Because assignment to `test` wasn't safely published, the
             // field could be null even if it was assigned "earlier" in real
             // time.
             return;
         }
         synchronized(test) {
             System.out.println(test.a); 
             // If no more modifications were made to 'a', this prints 5
             // (guaranteed). Without the synchronized blocks, this could 
             // print 0 (zero) or 5.
         }
     }
}

However in practice this is almost never useful, since you need to synchronization mechanism to safely pass the instance of Test from one thread to another, and the synchronization mechanism itself almost certainly already introduces a happens-before relationship between the threads.

Still it could have its use in some highly specific concurrency component.

Undoing answered 8/1, 2016 at 8:47 Comment(5)
What this wins is safe publication even over a data race. But since it relies on the receiver of the object explicitly taking the lock, it undermines the basic assumption of the above: that you want to be foolproof against code you don't control.Heaume
I don't get how test.a could print 0 without synchronized block... test would never be assigned before the constructor finishes execution, so test will either be null or test.a will be 5... Am i wrong?Suddenly
@MarkoTopolnik This question #34672718 has perhaps a better example; you can encapsulate both the constructor and the code that accesses the variable in the same classUndoing
@Suddenly without synchronization this is Incorrectly Synchronized Code. The write of the default variables is guaranteed to be visible to all threads but the subsequent assignment of 5 is not without a synchronization action. So the JVM and compiler together are not required to ever show the assignment of 5 in any other thread, until a happens-before relation is established between the thread that wrote the 5 and the thread that reads test.aUndoing
If you do that, then you have mutual exclusion of threads for no good purpose. Simply put, you cannot provide a good mechanism for safe publication over a data race unless all your fields are either final or volatile. As far as I'm following the discussions around the planned new Java Memory Model, it will remove the special status of final fields and provide the same guarantee to all fields.Heaume
K
0

May be you are changing some common data in constructor that is accessed by multiple threads. Though a better and simple approach would be preferred.

Kyte answered 22/2, 2013 at 10:21 Comment(0)
P
0

In normal conditions, there should be no reason why you would do that.

However, if you let the this reference "escape" the constructor (this is bad practice, of course), then you may want to force the client code to wait for the synchronized block to complete before invoking other operations.

For example:

class C {
    public C() {
        // ....
        synchronized(this) {
            someService.doSomethingWith(this);
            // some other critical stuff...
        }
    }

    public synchronized void criticalSection() {
        // ...
    }

}

In this example, if you invoke criticalSection() inside someService, you will be forced to wait until the synchronized block in the constructor is completed.

But again, this is not recommended and you should never allow this to escape the constructor.

Parallelism answered 22/2, 2013 at 10:23 Comment(0)
K
0

As far as I understand it can be critical if you deal with static fields inside a constructor. When object is under construction only thread which is creating it has an access to this object, but in case of changes of static field values in the constructor it can be an issue as two different threads can create objects of the same class simultaneously causing conflicts related to static fields. But not sure if it is a good idea to use this for locking

Kevel answered 18/9, 2015 at 20:18 Comment(0)
F
0

I think that Java flexibility allows to do that because inside a constructor you can do almost everything as a normal method (Methods vs Constructors in Java) but, is a bad practice if we are doing it. It's a matter of good practice here, we should no use synchronized blocks in constructors, there is no case where is better doing it inside a constructor.

Foretopmast answered 25/11, 2019 at 11:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.