首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java锁条件

Java锁条件
EN

Stack Overflow用户
提问于 2017-10-06 08:45:03
回答 1查看 238关注 0票数 2

假设我有以下代码:

代码语言:javascript
复制
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()。在此之后,如果时间还没有用完(或者是有的话,并且有资源存在-只是为了避免同时发生的情况),就会消耗一个资源。

问题是,有时资源被清空,获得resourcePresentCondition信号的线程抛出异常,因为资源列表是空的(.removeFirst()异常)。

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

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-10-06 09:53:54

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

这使得其他线程等待到发出信号或超时。没有办法恢复现有的await(),而且您也不希望开始编写自定义逻辑来跟踪等待的时间。

由于您使用的是公平锁(new ReentrantLock(true);) (在本例中应该如此),因此向所有线程发出信号都是没有意义的。你不想让一个拥有资源的消费者去竞争另一个资源。

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

代码语言:javascript
复制
// 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());
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46601787

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档