ここのコードを見ると、要素を取得する前にロックを取得する必要があることがわかります。多くのスレッドが取得している場合、このロックで競合が発生します。スレッドは何かが現れるのを待っているのではなく、他のスレッドが取得するのを待っています。
public E take() throws InterruptedException {
E x;
int c = -1;
final AtomicInteger count = this.count;
final ReentrantLock takeLock = this.takeLock;
takeLock.lockInterruptibly();
try {
try {
while (count.get() == 0)
notEmpty.await();
} catch (InterruptedException ie) {
notEmpty.signal(); // propagate to a non-interrupted thread
throw ie;
}
x = extract();
c = count.getAndDecrement();
if (c > 1)
notEmpty.signal();
} finally {
takeLock.unlock();
}
if (c == capacity)
signalNotFull();
return x;
}
編集
1 人のテイカーと多数のパターがいて、キューがいっぱいになり続ける場合、signalNotFull()
このコードによってボトルネックが発生します。
private void signalNotFull() {
final ReentrantLock putLock = this.putLock;
putLock.lock();
try {
notFull.signal();
} finally {
putLock.unlock();
}
}
putLock
これは、キューに現在スペースがあるという事実を通知するために を取る必要があります。