当我阅读ArrayBlockingQueue.take方法的源代码时,我遇到了问题。
我认为然后两个线程同时调用take方法,只有一个线程可以成功获取锁定,而另一个线程将等待该行的锁定:lock.lockInterruptibly();
这是take的源代码:
public E take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (count == 0)
notEmpty.await();
return dequeue();
} finally {
lock.unlock();
}
}
但是当我对这两个线程进行线程转储时,我发现两个线程都成功锁定并在线等待:notEmpty.await();
(因为队列为空)
这是线程转储:
“test-thread-18”#6357守护进程prio = 5 os_prio = 0 tid = 0x00007f8f54543000 nid = 0x58ef等待条件[0x00007f901bc70000] java.lang.Thread.State:WAITING(停车) 在sun.misc.Unsafe.park(原生方法) - 停车等待< 0x00007f93ae695410> (java.util.concurrent.locks.AbstractQueuedSynchronizer $ ConditionObject) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) at java.util.concurrent.locks.AbstractQueuedSynchronizer $ ConditionObject.await(AbstractQueuedSynchronizer.java:2039) at java.util.concurrent.ArrayBlockingQueue.take(ArrayBlockingQueue.java:403) at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127) at java.util.concurrent.ThreadPoolExecutor $ Worker.run(ThreadPoolExecutor.java:617) 在java.lang.Thread.run(Thread.java:745)
“test-thread-17”#6356守护程序prio = 5 os_prio = 0 tid = 0x00007f8f54542000 nid = 0x58ee等待条件[0x00007f901beb9000] java.lang.Thread.State:WAITING(停车) 在sun.misc.Unsafe.park(原生方法) - 停车等待< 0x00007f93ae695410> (java.util.concurrent.locks.AbstractQueuedSynchronizer $ ConditionObject) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) at java.util.concurrent.locks.AbstractQueuedSynchronizer $ ConditionObject.await(AbstractQueuedSynchronizer.java:2039) at java.util.concurrent.ArrayBlockingQueue.take(ArrayBlockingQueue.java:403) at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127) at java.util.concurrent.ThreadPoolExecutor $ Worker.run(ThreadPoolExecutor.java:617) 在java.lang.Thread.run(Thread.java:745)
那么,为什么两个不同的线程可以同时获得相同的锁? 我的理解有什么问题?
答案 0 :(得分:3)
只有一个线程可以同时保存ReentrantLock
。
notEmpty
是Condition
对象,当前线程会在调用Condition.await()
时解除锁定:
使当前线程等待,直到发出信号或 中断。与此条件关联的锁定是原子 发布,当前线程因线程调度而被禁用 目的和谎言一直处于休眠状态,直到四件事之一发生:
- 其他一些线程调用此Condition和的signal()方法 当前线程恰好被选为要被唤醒的线程;
- 或其他一些线程为此调用signalAll()方法 条件;
- 或其他一些线程中断当前线程,和 支持线程暂停的中断; - 或者A"虚假的唤醒" 发生。
在所有情况下,在此方法之前可以返回当前线程 必须重新获取与此条件相关的锁定。当。。。的时候 线程返回它保证保持此锁定。