Java ArrayBlockingQueue获取源代码
当我阅读ArrayBlockingQueue.take方法的源代码时,我遇到了一个问题 我认为两个线程同时调用take方法,只有一个线程可以成功地获得锁,而另一个线程将在以下行等待锁:Java ArrayBlockingQueue获取源代码,java,multithreading,concurrency,locking,Java,Multithreading,Concurrency,Locking,当我阅读ArrayBlockingQueue.take方法的源代码时,我遇到了一个问题 我认为两个线程同时调用take方法,只有一个线程可以成功地获得锁,而另一个线程将在以下行等待锁:lock.lockInterruptablely() 这是take的源代码: public E take() throws InterruptedException { final ReentrantLock lock = this.lock; lock.lockInterruptibly();
lock.lockInterruptablely()代码>
这是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=0x00007f8f5443000 nid=0x58ef等待条件[0x00007f901bc70000]
java.lang.Thread.State:等待(停车)
在sun.misc.Unsafe.park(本机方法)
-停车等待(java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
位于java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
位于java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
位于java.util.concurrent.ArrayBlockingQueue.take(ArrayBlockingQueue.java:403)
位于java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
位于java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
位于java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
运行(Thread.java:745)
“测试线程-17”#6356守护进程优先级=5 os_优先级=0 tid=0x00007F8F5442000 nid=0x58ee等待条件[0x00007f901beb9000]
java.lang.Thread.State:等待(停车)
在sun.misc.Unsafe.park(本机方法)
-停车等待(java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
位于java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
位于java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
位于java.util.concurrent.ArrayBlockingQueue.take(ArrayBlockingQueue.java:403)
位于java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
位于java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
位于java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
运行(Thread.java:745)
那么,为什么两个不同的线程可以在同一时间获得相同的锁呢?
我的理解有什么问题?只有一个线程可以同时持有可重入锁
notEmpty
是一个对象,当前线程将在调用时释放锁:
使当前线程等待,直到发出信号或
打断。与此条件相关的锁在原子上为
已释放,当前线程将被禁用以进行线程调度
在以下四种情况之一发生之前,目标和状态处于休眠状态:
- 其他一些线程为此条件调用signal()方法,并
当前线程恰好被选为要唤醒的线程李>
- 或者其他线程为此调用signalAll()方法
条件李>
- 或者其他线程中断当前线程,并且
支持中断挂线;
-还是“虚假的觉醒”
发生
在所有情况下,在该方法返回当前线程之前
必须重新获取与此条件相关的锁。当
线程返回并保证持有此锁
只有一个线程可以同时持有ReentrantLock
notEmpty
是一个对象,当前线程将在调用时释放锁:
使当前线程等待,直到发出信号或
打断。与此条件相关的锁在原子上为
已释放,当前线程将被禁用以进行线程调度
在以下四种情况之一发生之前,目标和状态处于休眠状态:
- 其他一些线程为此条件调用signal()方法,并
当前线程恰好被选为要唤醒的线程李>
- 或者其他线程为此调用signalAll()方法
条件李>
- 或者其他线程中断当前线程,并且
支持中断挂线;
-还是“虚假的觉醒”
发生
在所有情况下,在该方法返回当前线程之前
必须重新获取与此条件相关的锁。当
线程返回并保证持有此锁
您应该明确指出,notEmpty
绑定到lock
,因为这在问题中的代码中并不明显。谢谢。您指出了这个条件。wait()将释放锁,而a以前不知道。有了这些知识,我可以理解问题所在。您应该明确指出,notEmpty
与lock
绑定,因为这在问题中的代码中并不明显。谢谢。您指出了条件。await()将释放锁,这是a以前不知道的。有了这些知识,我就能理解问题所在。