Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why await of Condition releases the lock but signal does not?

I write the below code to test when will the thread is awake when it is waiting for a Condition object.

  1. But I find I have to unlock after I call signal(). Lock is not release by this method, while await() will release this lock .

This is from Condition#await

The lock associated with this Condition is atomically released and the current thread becomes disabled for thread scheduling purposes and lies dormant until one of four things happens:

And this is from Conditon#signal

Wakes up one waiting thread.

If any threads are waiting on this condition then one is selected for waking up. That thread must then re-acquire the lock before returning from await.

But in my code, this is not true, until we unlock the lock. Why it is design like this? Since in my opinion, when we decide to to signal the others, we should not hold the lock any more,am I wrong?

  1. Since we can do many things between calling signal and unlock ,say I sleep 10 seconds, what exactly the time java signal the other thread? Is there a another background thread who is working between we signal and unlock?

      public class  WorkerThread extends Thread{    
        @Override
        public void run() {
        Monitor.lock.lock();
        while (!Monitor.isConditionTrue){
            try {
                Monitor.condition.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("THREAD ID "+this.getId()+"-------working --------");
        System.out.println("------singnall--------");
        Monitor.isConditionTrue=true;
        Monitor.condition.signal();
            try {
               Thread.sleep(3000);//here, the thread is sleeping while another thread is not awaken since the lock is not releases
               System.out.println("------unlock--------");
               Monitor.lock.unlock();//now the other thread is awaken, if I do not explicitly unlock , no thread will be awaken.
            } 
           catch (InterruptedException e) {
                e.printStackTrace();
           }
        }
    }
    
    
    public class Monitor {
        static ReentrantLock lock = new ReentrantLock();
        static Condition condition = lock.newCondition();
        static volatile boolean isConditionTrue = true;
    
        public static void main(String args[]) {
            Thread t1 = new WorkerThread();
            Thread t2 = new WorkerThread();
            t1.start();
            t2.start();
            Thread.sleep(2000);
            lock.lock();
            isConditionTrue=true;
            condition.signalAll();
            lock.unlock();
        }
    
    }
    

OUTPUT:

THREAD ID 9-------working --------
------singnall--------
------unlock--------
THREAD ID 10-------working --------
------singnall--------
------unlock--------
like image 463
JaskeyLam Avatar asked Feb 12 '23 12:02

JaskeyLam


1 Answers

You have missed this sentence in Contition#await:

In all cases, before this method can return the current thread must re-acquire the lock associated with this condition. When the thread returns it is guaranteed to hold this lock.

In other words, you must explicitly release the lock after await, just as with signal.

Why this mechanism is sound: if you first released the lock, then signaled, you'd be open to race conditions where other threads made changes between releasing the lock and the signal reaching a parked thread. The way the mechanism works, first a definite thread is chosen to be awoken by the signal, then it waits for the lock, then the signaling thread releases it, then the awoken thread goes on.

You might argue that signal could do all of this internally, but then:

  1. the API would become confusing: there would be more than one method releasing the lock;
  2. the APi would become more restrictive and preclude any use cases where the thread wants to do something more before releasing the lock, such as atomically issuing more signals.
like image 121
Marko Topolnik Avatar answered Feb 14 '23 02:02

Marko Topolnik