Java ReentrantLock中Condition await()的锁释放机制咨询
问题解答
你的理解完全正确:cond.await()会让持有锁的ThreadOne进入等待状态,同时主动释放持有的ReentrantLock,这就是两个场景执行顺序不同的核心原因。下面分别拆解两种场景的执行逻辑:
场景一:调用cond.await()的情况
- ThreadOne先执行,通过
lock.lock()获取到ReentrantLock,打印Waiting 1 .... - 调用
cond.await():此时ThreadOne会主动释放持有的锁,同时进入Condition的等待队列,暂停执行 - ThreadTwo休眠1秒后尝试获取锁,因为ThreadOne已经释放锁,所以成功获取,打印
Waiting 2 .... - 等待用户输入回车后,ThreadTwo调用
cond.signal()唤醒等待队列中的ThreadOne,但此时ThreadTwo仍持有锁,所以ThreadOne虽被唤醒,仍需等待ThreadTwo释放锁才能继续执行 - ThreadTwo执行完
increment()后,在finally块中调用lock.unlock()释放锁 - 锁释放后,ThreadOne重新获取锁,继续执行后续代码:打印
Woken up!、执行increment(),最后释放锁
场景二:注释掉cond.await()的情况
- ThreadOne调用
lock.lock()获取锁后,因为没有调用await(),不会释放锁,直接打印Waiting 1 ....和Woken up! - ThreadOne完整执行完
increment()后,才在finally块中调用lock.unlock()释放锁 - ThreadTwo在此之前尝试获取锁时,会因锁被ThreadOne持有而进入阻塞状态,直到ThreadOne释放锁后,才能获取锁并执行自身逻辑
第一段代码(带cond.await())
public class ExecProgram { private int count = 0; private Lock lock = new ReentrantLock(); private Condition cond = lock.newCondition(); private void increment(String threadName) { for (int i = 0; i < 5; i++) { count++; System.out.println("Incremented by "+threadName); } } public void ThreadOne() throws InterruptedException { lock.lock(); System.out.println("Waiting 1 ...."); cond.await(); System.out.println("Woken up!"); try { increment("Thread1"); } finally { System.out.println("Waiting done 1 ...."); lock.unlock(); } } public void ThreadTwo() throws InterruptedException { Thread.sleep(1000); lock.lock(); System.out.println("Waiting 2 ...."); System.out.println("Press the return key!"); new Scanner(System.in).nextLine(); System.out.println("Rcvd return key!"); cond.signal(); try { increment("Thread2"); } finally { System.out.println("Waiting done 2 ...."); //should be written to unlock Thread whenever signal() is called lock.unlock(); } } public void finished() { System.out.println("Count is: " + count); } }
第一段输出
Waiting 1 .... Waiting 2 .... Press the return key! Rcvd return key! Incremented by Thread2 Incremented by Thread2 Incremented by Thread2 Incremented by Thread2 Incremented by Thread2 Waiting done 2 .... Woken up! Incremented by Thread1 Incremented by Thread1 Incremented by Thread1 Incremented by Thread1 Incremented by Thread1 Waiting done 1 .... Count is: 10 Time taken 4112
第二段代码(注释掉cond.await()及相关代码)
public void ThreadOne() throws InterruptedException { lock.lock(); System.out.println("Waiting 1 ...."); // cond.await(); System.out.println("Woken up!"); try { increment("Thread1"); } finally { System.out.println("Waiting done 1 ...."); lock.unlock(); } }
public void ThreadTwo() throws InterruptedException { // Thread.sleep(1000); lock.lock(); System.out.println("Waiting 2 ...."); /* System.out.println("Press the return key!"); new Scanner(System.in).nextLine(); System.out.println("Rcvd return key!"); cond.signal(); */ try { increment("Thread2"); } finally { System.out.println("Waiting done 2 ...."); //should be written to unlock Thread whenever signal() is called lock.unlock(); } }
第二段输出
Waiting 1 .... Woken up! Incremented by Thread1 Incremented by Thread1 Incremented by Thread1 Incremented by Thread1 Incremented by Thread1 Waiting done 1 .... Waiting 2 .... Incremented by Thread2 Incremented by Thread2 Incremented by Thread2 Incremented by Thread2 Incremented by Thread2 Waiting done 2 .... Count is: 10 Time taken 11
内容的提问来源于stack exchange,提问作者user3153356
相关产品推荐
相关产品推荐

