简体   繁体   English

Java ArrayBlockingQueue获取源代码

[英]Java ArrayBlockingQueue take source

When I was reading source code of ArrayBlockingQueue.take method, I got a problem. 当我阅读ArrayBlockingQueue.take方法的源代码时,遇到了一个问题。

I think then two threads call take method concurrently, only one thread could successfully get lock, and the other thread would waiting on the lock at the line: lock.lockInterruptibly(); 我认为然后有两个线程同时调用take方法,只有一个线程可以成功获得锁,而另一个线程将在该行等待锁: lock.lockInterruptibly(); this is source code of take: 这是take的源代码:

public E take() throws InterruptedException {
    final ReentrantLock lock = this.lock;
    lock.lockInterruptibly();
    try {
        while (count == 0)
            notEmpty.await();
        return dequeue();
    } finally {
        lock.unlock();
    }
}

But when I make a thread dump of the two threads, I found that both threads got lock successfully, and waiting on line: notEmpty.await(); 但是,当我对两个线程进行线程转储时,我发现两个线程都已成功锁定,并在线等待: notEmpty.await(); (because queue is empty) This is the thread dump: (因为队列为空),这是线程转储:

"test-thread-18" #6357 daemon prio=5 os_prio=0 tid=0x00007f8f54543000 nid=0x58ef waiting on condition [0x00007f901bc70000] java.lang.Thread.State: WAITING (parking) at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x00007f93ae695410> (a 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) at java.lang.Thread.run(Thread.java:745) “ test-thread-18”#6357守护程序prio = 5 os_prio = 0 tid = 0x00007f8f54543000 nid = 0x58ef等待条件[0x00007f901bc70000] java.lang.Thread.State:在sun.misc.Unsafe.park(Native)处等待(停车)方法)-停放以等待java.util.concurrent上的<0x00007f93ae695410>(java.util.concurrent.locks.AbstractQueuedSynchronizer $ ConditionObject)在java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)处。 java.util.concurrent.ArrayBlockingQueue.take(ArrayBlockingQueue.java:403:java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)上的locks.AbstractQueuedSynchronizer $ ConditionObject.await(AbstractQueuedSynchronizer.java:2039) .util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)at java.util.concurrent.ThreadPoolExecutor $ Worker.run(ThreadPoolExecutor.java:617)at java.lang.Thread.run(Thread.java:745)

"test-thread-17" #6356 daemon prio=5 os_prio=0 tid=0x00007f8f54542000 nid=0x58ee waiting on condition [0x00007f901beb9000] java.lang.Thread.State: WAITING (parking) at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x00007f93ae695410> (a 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) at 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:正在sun.misc.Unsafe.park(本机)等待(停车)方法)-停放以等待java.util.concurrent上的<0x00007f93ae695410>(java.util.concurrent.locks.AbstractQueuedSynchronizer $ ConditionObject)在java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)处。 java.util.concurrent.ArrayBlockingQueue.take(ArrayBlockingQueue.java:403:java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)上的locks.AbstractQueuedSynchronizer $ ConditionObject.await(AbstractQueuedSynchronizer.java:2039) .util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)at java.util.concurrent.ThreadPoolExecutor $ Worker.run(ThreadPoolExecutor.java:617)at java.lang.Thread.run(Thread.java:745)

So, why two different thread could get the same lock on same time? 那么,为什么两个不同的线程可以在同一时间获得相同的锁? What's wrong with my understand? 我的理解有什么问题?

Only one thread can hold the ReentrantLock on the same time. 只有一个线程可以同时持有ReentrantLock

notEmpty is an Condition object, current thread will release the lock when calling Condition.await() : notEmpty是一个Condition对象,当前线程在调用Condition.await()时将释放锁:

Causes the current thread to wait until it is signalled or interrupted. 使当前线程等待,直到发出信号或被中断为止。 The lock associated with this Condition is atomically released and the current thread becomes disabled for thread scheduling purposes and lies dormant until one of four things happens: 与此条件相关联的锁被原子释放,并且出于线程调度目的,当前线程被禁用,并且处于休眠状态,直到发生以下四种情况之一:

  • Some other thread invokes the signal() method for this Condition and the current thread happens to be chosen as the thread to be awakened; 其他一些线程为此条件调用signal()方法,并且当前线程恰好被选择为要唤醒的线程;
  • or Some other thread invokes the signalAll() method for this Condition; 或其他一些线程为此条件调用signalAll()方法;
  • or Some other thread interrupts the current thread, and interruption of thread suspension is supported; 或其他一些线程中断当前线程,并支持中断线程挂起; -or A "spurious wakeup" occurs. -或者发生“虚假唤醒”。

In all cases, before this method can return the current thread must re-acquire the lock associated with this condition. 在所有情况下,在此方法可以返回之前,当前线程必须重新获取与此条件关联的锁。 When the thread returns it is guaranteed to hold this lock. 当线程返回时,可以保证保持此锁。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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