gpt4 book ai didi

java - 为什么ReentrantLock with Conditions可以被ArrayBlockingQueue中的两个线程获取

转载 作者:行者123 更新时间:2023-11-30 08:34:01 25 4
gpt4 key购买 nike

这可能是一个愚蠢的问题,但我无法理解为什么单个 ReentrantLock 可以被此类中的两个不同线程占用(这是我以前玩线程和锁的 ArrayBlockingQueue 的简化解决方案):

class SampleThreadSafeQueue {

private ReentrantLock lock = new ReentrantLock();
private List<Integer> list = new ArrayList<>();
private Condition notEmpty;
private Condition notFull;
private volatile int count;

public SampleThreadSafeQueue() {
notEmpty = lock.newCondition();
notFull = lock.newCondition();
}

public int take() {
try {
lock.lock();
System.out.println(Thread.currentThread().getName() +": acquired lock in take()");
while (count == 0) {
notEmpty.await();
}

return extract();
} catch (Exception e) {
e.printStackTrace();
return 0;
} finally {
System.out.println(Thread.currentThread().getName() +": released lock for take()");
lock.unlock();
}
}

private int extract() {
int index = count <= 0 ? 0 : count - 1;
Integer integer = list.get(index);
list.remove(index);
count--;
list.clear();
notFull.signal();
return integer;
}

public void put(int value) {
try {
lock.lock();
System.out.println(Thread.currentThread().getName() +": acquired lock in put()");
while (!list.isEmpty()) {
notFull.await();
}
Thread.sleep(3000); // let's assume it takes 3 secs to add value
insert(value);
} catch (Exception e) {
e.printStackTrace();
} finally {
System.out.println(Thread.currentThread().getName() +": released lock for put()");
lock.unlock();
}
}


private void insert(int value) {
list.add(value);
count = list.size();
notEmpty.signal();
}
}

我在控制台中收到此结果:

pool-1-thread-1: acquired lock in put()
pool-1-thread-1: released lock for put()
pool-1-thread-1: acquired lock in put() - this guy has taken the lock
pool-1-thread-2: acquired lock in take() - that guy has taken the lock as well! wtf?
pool-1-thread-2: released lock for take()
Value = 0
pool-1-thread-2: acquired lock in take()
pool-1-thread-1: released lock for put()
pool-1-thread-1: acquired lock in put()
pool-1-thread-2: released lock for take()
Value = 1
pool-1-thread-1: released lock for put()
pool-1-thread-1: acquired lock in put()
pool-1-thread-2: acquired lock in take()
pool-1-thread-2: released lock for take()
Value = 2
...

我怀疑这是因为我在 while 循环中使用了条件,但逻辑上无法理解为什么会发生。感谢您的解释。谢谢!

最佳答案

当您在从某个锁获得的Condition 上调用await() 时,您的线程会释放锁并停止,直到Condition从另一个线程通知(通过 signal()signalAll())。

因此,您的线程 1 获取锁,但随后调用 await() 并切换到等待模式,释放线程 2 最近获取的锁。当线程 2 完成后,它通知线程 1(通过调用 signal())并释放锁。锁立即被线程 1 重新获取,它醒来并继续工作,最后释放锁。

然后他们以稍微不同的顺序重复它。

关于java - 为什么ReentrantLock with Conditions可以被ArrayBlockingQueue中的两个线程获取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39110410/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com