Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why Lock condition await must hold the lock

Tags:

I am in doubt with that , in Java language, we need to acquire the lock, before we await some condition to be satisfied.

For example, int java monitor lock:

synchronized(lock){    System.out.println("before lock ...");    lock.wait();    System.out.println("after lock ..."); } 

or the concurrency utils:

Lock lock = new ReentrantLock(); Condition cond = lock.newCondition();  lock.lock(); try{      System.out.println("before condition ...");      cond.await();      System.out.println("after condition ..."); }catch(Exception e){      e.printStackTrace(); }finally{      lock.unlock(); } 

So, why we can't await, without hold the lock ?

Does other languages differ, or it's just in Java?

I hope you can explain the reason after the design, but not only for JAVA-SPEC definition.

like image 698
Chinaxing Avatar asked Sep 25 '15 03:09

Chinaxing


People also ask

Does condition await release lock?

The key property that waiting for a condition provides is that it atomically releases the associated lock and suspends the current thread, just like Object.

What does lock lock () do?

The lock() method is one of the most important methods of the Lock interface. It is used for acquiring the lock. For thread scheduling purposes, the current thread becomes disabled when the lock is not available. The lock() method is a public method that returns void.

What is conditional locking?

Conditional Locking allows to create sophisticated locking contracts for thread synchronization when threads are interdependent. Using conditional Locking we can cater the flow of program gracefully based on lock acquisition and conditions.

How does lock work in multithreading?

A lock may be a tool for controlling access to a shared resource by multiple threads. Commonly, a lock provides exclusive access to a shared resource: just one thread at a time can acquire the lock and everyone accesses to the shared resource requires that the lock be acquired first.


1 Answers

Imagine you have something that a thread might need to wait for. Maybe you have a queue and a thread needs to wait until there's something on the queue so it can process it. The queue must be thread-safe, so it has to be protected by a lock. You might write the following code:

  1. Acquire the lock.
  2. Check if the queue is empty.
  3. If the queue is empty, wait for the something to be placed on the queue.

Oops, that won't work. We hold the lock on the queue so how can another thread place something on it? Let's try again:

  1. Acquire the lock.
  2. Check if the queue is empty.
  3. If the queue is empty, release the lock and wait for the something to be placed on the queue.

Oops, now we still have a problem. What if after we release the lock but before we wait for something to be placed on the queue, something is placed on the queue? In that case, we will be waiting for something that already happened.

Condition variables exist to solve this exact problem. They have an atomic "unlock and wait" operation that closes this window.

So await must hold the lock because otherwise there would be no way to ensure you weren't waiting for something that already happened. You must hold the lock to prevent another thread from racing with your wait.

like image 132
David Schwartz Avatar answered Mar 06 '23 06:03

David Schwartz