javamultithreadingsynchronizedlocks

Are not multiple threads able to enter a synchronized block at the same time?


I am new to Java and came across this link: http://tutorials.jenkov.com/java-concurrency/slipped-conditions.html while understanding multithreading in java.

In this tutorial the code below is called out as a good practice to avoid slipped conditions:

public class Lock {

    private boolean isLocked = true;

    public void lock(){
      synchronized(this){
        while(isLocked){
          try{
            this.wait();
          } catch(InterruptedException e){
            //do nothing, keep waiting
          }
        }
        isLocked = true;
      }
    }

    public synchronized void unlock(){
      isLocked = false;
      this.notify();
    }

}

My doubt is that in case two threads A & B call lock() at the same time and isLocked is true i.e. lock has been taken by some other thread C. Now:

--1 A enters synchronized block first (as only one can obtain lock on monitor-object this and enter a synchronized block) --2 A calls this.wait() and so releases lock on monitor-object this (wait() call releases the lock on monitor-object http://tutorials.jenkov.com/java-concurrency/thread-signaling.html#wait-notify) but remains inside synchronized block --3 Now B enters synchronized block (as A has released lock on monitor-object this) --4 B calls this.wait() and so releases lock on monitor-object this (wait() call releases the lock on monitor-object) --5 at this moment thread C calls unlock() i.e. sets isLocked to false and calls this.notify() --6 Now one of A and B come out wait(), then come out of while loop and set isLocked to true --7 and the cycle continues

So in --3, both A and B are inside a synchronized block at the same time, is it not in violation of the basic multithreading principle that only one thread is allowed inside a synchronized block at a time?

Please clarify my doubt.


Solution

  • A thread can only return from the wait() method if it reacquires the lock on the object it's waiting on. In your scenario, A and B would compete to get the lock, only one of them would get it and the other one would keep waiting until the lock is released again.

    From the javadoc (emphasis mine):

    The current thread must own this object's monitor. The thread releases ownership of this monitor and waits until another thread notifies threads waiting on this object's monitor to wake up either through a call to the notify method or the notifyAll method. The thread then waits until it can re-obtain ownership of the monitor and resumes execution.