私のアプリケーションでは、次の 2 つのことが起こります。
- さまざまなスレッドがジョブを生成します。
- ジョブを消費する関数があります (ただし、常に実行されているスレッドは 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() を呼び出すまで実行されません。
実際に問題が発生するとは思えませんが、この小さなギャップを正確に埋めることができますか?