6

Today I was asked this interview question and could not answer. If you have two instances of a Person class which has a setAddress method that is synchronized. Now if it was only one object and multiple threads were accessing it, the synchronized will make sure that only one method can access it at a time.

But if there are different objects, one thread will not wait on the other before entering the method.

Now the question is...if I wanted to make the method synchronized across all instances of Person Objects, how do I do that?

  • 2
    Sounds like a trick question, or I'm misunderstanding what you're saying, or you're not explaining it right. If it's an instance method, then it doesn't matter if there are other instances of that object unless the instance(s) access some shared, mutable, state. – Steven Evers Jul 31 '13 at 22:15
  • what about accross EC2 4 instances ? – shareef Dec 11 '16 at 11:42
12

Synchronize on the Person.class or create a static LOCK object on which you synchronize:

synchronize(Person.class){
    //...
}

or

private static final Object LOCK = new Object();

//...
synchronize(LOCK){
    //...
}

Either way, we're using a single (static) lock object instance which is common to all callers. Synchronizing on the class mirrors the default behavior of synchronized static methods. But it somewhat exposes the lock, which can be dangerous because for instance, some evil code could synchronize on Person.class and never release the lock, and make your code jam up. Keeping a separate private lock is therefore more secure.

  • 3
    Explain why that works. – Robert Harvey Jul 31 '13 at 22:56
  • 4
    Locking on a private static field is MUCH safer than locking the class itself. Locking the class breaks encapsulation and gives up control of the lock to anything can see the class. – Despertar Jul 31 '13 at 23:00
  • @Despertar Interesting then that the class is used for synchronizing static methods - e.g. see this answer – Steve Chambers Sep 14 '15 at 10:53
  • 2
    @SteveChambers - this is regarded by some as a design flaw in Java's synchronization system (as is the fact that synchronized instance methods synchronize on the instance); it would have been better if in both cases the methods synchronized on a hidden lock object rather than on the class/owner object, as doing so increases encapsulation, but unfortunately it can no longer be changed without breaking compatibility and there's not enough benefit for anyone to want to do that. See: blog.jooq.org/2016/01/12/… – Periata Breatta Sep 11 '16 at 18:30
  • @PeriataBreatta Yep, it's also one of the issues with the seamless introduction of value-types in Java, that any Object can suddenly be asked to provide synchronization machinery. Still, back in the early 1990s, this was all considered a leading-edge marvel of cleverness, helping every Object to be an Actor... – SusanW Oct 8 '16 at 16:55
0

Make the setAddress() method static along with synchronized. Basically, you would be making the setAddress() method global so that only one copy of this method exists and by making synchronized only one thread would be entering this method.

public synchronized static void setAddress(){ //... }

There is a drawback: All the instance variables will 've to be made static. As only static variables can be accessed from the static method.

  • I'm not sure why this is downvoted so harshly. It's a valid solution to the problem, albeit probably not as good as the existing answer, but the option should be considered. – Periata Breatta Sep 11 '16 at 18:31
  • This is no valid solution to the problem. And with the last paragraph (which is wrong - passing the Person would make this a horrible workaround at least) it will make the Person class completely useless, as all Persons now share the same data. – Eiko Oct 9 '16 at 9:25

Not the answer you're looking for? Browse other questions tagged or ask your own question.