0

在我的应用程序中,发生了两件事:

  • 各种线程产生工作。
  • 有一个函数(但不是 1 个持续运行的线程)消耗这些作业。此功能由生产者启动,但被锁定,因此它只运行一次。

例如,生成了一个作业:

addJobToDatabase(...);
triggerPass();

这就是消费者功能的启动方式:

public void triggerPass() {

    // prevent running more than once
    if (onceLock.tryLock()) { // onceLock is a ReentrantLock
        try {

            while (haveJobs()) {
                doJobs();
            }

        } finally {
            onceLock.unlock();
        }
    } else {
        log.info("Pass triggered, but already running");
    }

}

现在,这里可能存在一个很小的竞争条件。如果

  • 线程 A 已离开while但尚未完成onceLock.unlock()
  • 线程 B 会onceLock.tryLock()返回 false

...线程 B 的作业直到稍后调用 triggerPass(); 才会执行;

虽然我怀疑它会在实践中给我带来麻烦,但这个小差距可以为了正确性而缩小吗?

4

2 回答 2

0

不幸的是,在这种设计中,竞争条件是不可避免的。想要它是正确的吗?你为什么不创建像迭代器或队列之类的东西,其中读-修改-写操作是单个原子操作?

public void triggerPass() {
    Job job = null; 
    while ((job = jobIterator.next()) != null) {
        doJob(job);
    }
}
于 2012-12-10T16:19:32.737 回答
0

我想我已经通过替换来解决tryLock()tryLock(1, TimeUnit.SECONDS)。但这并不好,如果 和 之间的延迟超过 1 秒(谁知道数据库中发生了什么),这甚至不是万无一失there are no more jobsunlock()

于 2012-12-10T13:48:06.410 回答