gpt4 book ai didi

java - Java锁定条件

转载 作者:行者123 更新时间:2023-12-03 12:59:23 24 4
gpt4 key购买 nike

假设我有以下代码:

private final ReentrantLock resourcesLock = new ReentrantLock(true);
private Condition resourcePresentCondition= resourcesLock.newCondition();

public void requestRes() throws InterruptedException {
resourcesLock.lock();
try {
if(resources.isEmpty()) {
if(!resourcePresentCondition.await(Config.STARVE_TIME_SECONDS, TimeUnit.SECONDS)) {
if(resources.isEmpty()) {
return;
}
}
}
//No resources left if other threads gather them first
Resource resource = resources.removeFirst();
} finally {
resourcesLock.unlock();
}
}

现在,多个线程进入requestRes()方法,如果没有资源存在,它们都将等待条件。另一种方法生成资源并调用 resourcePresentCondition.signalAll()。此后,如果时间还没有用完(或者如果时间用完了,并且存在资源-只是为了避免所有情况都在同一时间发生),则会消耗资源。

问题在于,有时资源会被清空,并且由于资源列表为空(.removeFirst()异常),获得resourcePresentCondition信号的线程会引发异常。

避免这种情况并使线程恢复对resourcePresentCondition的等待(而不是重新开始)的最佳解决方案是什么?

最佳答案

最简单的方法是仅使用signal()而不是signalAll,对添加的每个资源调用一次signal()。这样可以确保每个发出信号的线程都保证有1个资源可以使用。

这使其他线程等待,直到发出信号或发生超时。无法恢复现有的await(),并且您不想开始编写自定义逻辑来跟踪等待时间。

由于您使用的是公平锁(new ReentrantLock(true);)(在这种情况下,您应该如此),所以甚至没有必要发出所有线程信号。您不希望有资源的消费者去竞争另一个消费者。

可以简化事情的另一种方法是使用公平的Semaphore

// Consumer
private final Semaphore semaphore = new Semaphore(0, true);

public void requestRes() throws InterruptedException {
if(!semaphore.tryAcquire(Config.STARVE_TIME_SECONDS, TimeUnit.SECONDS))
return; // No resource available, and timed out

Resource resource = resources.removeFirst();
}

// Producer, giving out as many semaphores as resources produced
semaphore.release(resources.size());

关于java - Java锁定条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46601787/

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