简体   繁体   中英

Is a reentrant lock released when calling its condition.await?

I have the following code:

public class Synchronizer {

    private final Lock lock = new ReentrantLock();
    private final Condition done = lock.newCondition();
    private boolean isDone = false;

    private void signalAll() {

        lock.lock(); // MUST lock!
        try {
            isDone = true; // To help the await method ascertain that it has not waken up 'spuriously'
            done.signalAll();
        }
        finally {
            lock.unlock(); // Make sure to unlock even in case of an exception
        }
    }

    public void await() {

        lock.lock(); // MUST lock!
        try {
            while (!isDone) { // Ascertain that this is not a 'spurious wake-up'
                done.await();
            }
        }
        finally {
            isDone = false; // for next time
            lock.unlock(); // Make sure to unlock even in case of an exception
        }
    }
}

Suppose thread 1 calls synchornizer.await() and acquires the lock via the

lock.lock();

and blocks on the

done.await();

Then another thread 2 calls synchronizer.signalAll() in order to signal thread 1. My question is how is thread 2 ever able to acquire the lock by calling

lock.lock();

before calling

done.signallAll();

when the lock was initially acquired by thread 1?

I found the same question here:

Waiting on a condition in a reentrant lock

The answer says:

Both Lock and synchronized temporarily allow others to obtain the lock when they are waiting. To stop waiting, a thread have to re-acquire the lock.

I am trying to understand does this mean that thread 2 would not be able to acquire the lock if thread 1 did not call done.await()?

Also the answer states that:

Note: They don't release it fully and if you take a stack trace you can have multiple threads which appear to be holding the lock at once, but at most one of them will be running (the rest will be waiting)

Yet the documentation for Condition.await() states that:

The lock associated with this Condition is atomically released

So is the lock released or not and what "They don't release it fully" mean?

  1. Thread 1 (T1) will acquire lock at #await() lock.lock() call
  2. T1 will release lock at #await() done.await(). T1 will park untill signaled or interupted or "spurious waked"*
  3. T2 will acquire lock at #signallAll() lock.lock
  4. T2 will signal waking up #signallAll() done.signalAll
  5. T2 will release lock #signallAll() lock.unlock
  6. T1 will wake up at #await() done.await()
  7. T1 will acquire lock #await() done.await()
  8. T1 will release lock #await() lock.unlock()

T1 could be "spurious waked" at any point of running T2. But this will happen within done.await call. Control will never be retured to caller code unless associated lock is unlocked and other conditions for releasing are not right (thread must be signaled or interupted).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM