2

Consider a class that represents a simple cell:

class Cell {
    private int x;

    Cell(int x) {
        this.x = x;
    }

    int getX() {
        return x;
    }

    void setX(int x) {
        this.x = x;
    }
}

If I want to make it thread-safe, should I only make the methods synchronized or the constructor too?

class Cell {
    private int x;

    Cell(int x) {
        synchronized(this) { // <- Is this synchronization necessary?
            this.x = x;
        }
    }

    synchronized int getX() {
        return x;
    }

    synchronized void setX(int x) {
        this.x = x;
    }
}

If yes, why are there no synchronized blocks in java.util.Vector constructors?

ZhekaKozlov
  • 36,558
  • 20
  • 126
  • 155
  • 1
    Why would several threads create the same object reference? – Luiggi Mendoza Apr 11 '14 at 15:26
  • Since none of your items in Cell are static do you plan on accessing the same instance of Cell across multiple threads? – user3507600 Apr 11 '14 at 15:27
  • http://stackoverflow.com/q/4880168/738746 – Bhesh Gurung Apr 11 '14 at 15:28
  • One thread can create an object, and the other thread can access it. I think it is possible that the second thread can see the default value of `x` (0) instead of the provided value, because there is no `happens-before` relationship between writing a value in the constructor and reading the value in `getX`. – ZhekaKozlov Apr 11 '14 at 15:28
  • @BheshGurung Thanks, but there is no answer there. – ZhekaKozlov Apr 11 '14 at 15:29
  • @orionll I would think that you would want to synchronize the getter for Cell, and in the getter insure that it's been initialized. But you may want to synchronize the methods if it's being used in multiple threads. – user3507600 Apr 11 '14 at 15:31
  • "There is no practical need for a constructor to be synchronized, because it would lock the object under construction, which is normally not made available to other threads until all constructors for the object have completed their work." is quoted by tackline, I think that answers your doubt. – Bhesh Gurung Apr 11 '14 at 15:32
  • 1
    @orionll Of course there is. The other thread cannot hold a reference to the object before the constructor finishes (unless the constructor itself passes `this` to the other thread, but that would be asking for trouble). – Axel Apr 11 '14 at 15:53

5 Answers5

5

As per the JLS#8.8.3

There is no practical need for a constructor to be synchronized, because it would lock the object under construction, which is normally not made available to other threads until all constructors for the object have completed their work.

So that implies the reference is being synchronized prior to be accessible.

Since you are correctly synchronizing, it would be said writes that occur in the constructor would happen-before the object is published, so long as the synchronization is consistent on said field

In your case since getX() and setX() are both synchronized, the synchronization is consistent and you do not need to sync in the constructor.


Now, would you ever need to synchronize(this) on the constructor? No, as the JLS mentions it is implicitly synchronizing without you knowing about it.

John Vint
  • 39,695
  • 7
  • 78
  • 108
  • 1
    As an addition, it would be wise marking the `x` field as `volatile`. – Luiggi Mendoza Apr 11 '14 at 15:47
  • 1
    +1 Luiggi: It would be, however, since OP is correctly synchronizing on both read and write I left that out. – John Vint Apr 11 '14 at 15:48
  • @JohnVint What will happen if i am accessing public static variable in the constructor . Still i dont need to wrap those block ? – Mani Apr 11 '14 at 16:24
  • 1
    @Mani I did mention you didn't need to `synchronize(this)`, but if you are referencing a static variable, and that variable is being synchronized else where, you would also need to synchronize similarly in the constructor. Synchronizing on `this` is virtually a noop – John Vint Apr 11 '14 at 17:05
  • 1
    @JohnVint Thanks for the clarification. That is my understanding too. i am tring to understand the downvote reason on my answer :) . i dont know who ever did that. but i want to check wether my understanding is correct or not . thanks. – Mani Apr 11 '14 at 17:11
1

This brings up an important tangential point - you should never allow a reference to an object to escape from its constructor, as this would allow access to a partially constructed object.

So assuming that you follow this iron law of programming, you never need to synchronize a constructor, as no method, concurrent or otherwise, can access an object before the constructor returns. Thus synchronizing makes no logical sense.

phil_20686
  • 4,000
  • 21
  • 38
0

No, you don't need to synchronize the constructor, because as long as you are in the constructor, the reference cannot be leaked to another thread.

Besides that:

  1. Consider making your class immutable. Then no synchronisation is needed.
  2. I'd rather not make a simple class like this synchronzid but leave synchronisation to the user of the classs. You don't need synchronisation, if the same object is only accessed from one thread.
Axel
  • 13,939
  • 5
  • 50
  • 79
  • That is not enough to be thread-safe. Even if the reference becomes available after the construction of the object, there is possibility that a different thread will see the stale value of `x` (which is 0 by default). – ZhekaKozlov Apr 11 '14 at 15:35
  • @orionll Can you explain in more detail and/or post a reference? – Axel Apr 11 '14 at 15:42
-1

You don't required for your situation.

  1. if you are accessing the sharable data then you need to wrap by sych block.

In your case, you are accessing the instance variable which is only accessible / visible to only one thread since you are in constructor. You will call constructor , you are allocating the memory and end of method call returning unique pointer to calling method so the pointer/instance is unique for the Thread.

Once the pointer received. if the pointer /object variable shared in multiple threads like this.

Object obj = new Object();
Thread t1 = new Thread(new x(obj)); 
Thread t2 = new Thread(new x(obj));

Class x implements runnable{
 Object obj;
 x (Object obj){
   this.obj = obj;
 }

run() {
 // do some operation on Obj  -
}
}

}

in this case obj is shared across multiple threads , so your instance variable x subject for race condition. So you have make sure to wrap in other methods.

Thats why vector constructor is not having sycn block but other method does.

Assume you have one static variable in this class . then it is required to wrap by sync block since it is accessible to any one.

Mani
  • 3,274
  • 2
  • 17
  • 27
-2

Constructors should never be synchronized because I guess it is not practical.(When will you need to call a same constructor from different places at a same time?)

Here is the further information:

Bipin Bhandari
  • 2,694
  • 23
  • 38
  • 1
    The reason should be "When will you need to call the constructor for the same object from different places at the same time" ... as it is not possible, but what you wrote surely is. – Daniel Apr 11 '14 at 15:33