3

I have this class:

public class MyClass {

    public MyClass(){}

    public void actionA(){
        synchronized(MyClass.class){
            System.out.print("A");
        }
    }

    public void actionB(){
        synchronized(MyClass.class){
            actionA();
        }
    }

}

Which one (if any) is true?

  1. Calling actionB() will lead to a deadlock, since actionA() can never aquire the lock associated with MyClass.class
  2. Calling actionB() will not lead to a deadlock, since it already has aquired the lock associated with MyClass.class
cdriver
  • 155
  • 1
  • 12

2 Answers2

2

#2 will happen, since the calling thread has the lock.

If however the code looked like this:

public void actionB(){
    synchronized(MyClass.class) {
      Thread thread = new Thread(new Runnable { run() { actionA(); }});
      thread.start();
      thread.join();
    }
}

Then you would have a deadlock. locks are acquired on a per thread basis.

I find a useful mental picture is of a shared key for a padlock. Only one thread can have the key at a time, but obviously the same key will open any lock which it fits (the key fits any lock that uses the same sync object).

As an aside, it is bad practice to synchronize on any publicly visible field, since another piece of code far removed could feasibly lock on the same object leading to unnecessary contention and possibly deadlocks.

Rich O'Kelly
  • 41,274
  • 9
  • 83
  • 114
  • synchronized is not just a lock . if already aquireed by the thread , it just continues. it's also easy to test the code you've written and see it for yourself. same goes to ReentrantLock – android developer May 18 '12 at 14:02
  • I'll check this answer as correct as rich.okelly answered first. – cdriver May 18 '12 at 14:06
2

#2 will be happen.

Reentrant Synchronization

Recall that a thread cannot acquire a lock owned by another thread. But a thread can acquire a lock that it already owns. Allowing a thread to acquire the same lock more than once enables reentrant synchronization. This describes a situation where synchronized code, directly or indirectly, invokes a method that also contains synchronized code, and both sets of code use the same lock. Without reentrant synchronization, synchronized code would have to take many additional precautions to avoid having a thread cause itself to block.

Pau Kiat Wee
  • 9,485
  • 42
  • 40
  • Actually, it is simple now that i think about it. It seems i was confused as i wasn't sure who is waiting for the lock - it is the thread, not the calling block. – cdriver May 18 '12 at 14:09