より高いレベルの構成でいくつかの試みを試みましたが、何も思い浮かびませんでした. これは、低レベルの API に落とし込む機会になると思います。
編集:私は実際にあなたが本質的にトリッキーな問題を設定しようとしていると思います(最後の段落の2番目から2番目を参照)そしておそらく必要ではありません(最後の段落を参照)。しかし、そうは言っても、これを行う方法は次のとおりです。この回答の最後に色の解説を残します.
private int someMethod1Invocations = 0;
private int someMethod2Invocations = 0;
public void someMethod1() {
synchronized(this) {
// Wait for there to be no someMethod2 invocations -- but
// don't wait on any someMethod1 invocations.
// Once all someMethod2s are done, increment someMethod1Invocations
// to signify that we're running, and proceed
while (someMethod2Invocations > 0)
wait();
someMethod1Invocations++;
}
// your code here
synchronized (this) {
// We're done with this method, so decrement someMethod1Invocations
// and wake up any threads that were waiting for that to hit 0.
someMethod1Invocations--;
notifyAll();
}
}
public void someMethod2() {
// comments are all ditto the above
synchronized(this) {
while (someMethod1Invocations > 0)
wait();
someMethod2Invocations++;
}
// your code here
synchronized(this) {
someMethod2Invocations--;
notifyAll();
}
}
上記の明らかな問題の 1 つは、スレッドの枯渇につながる可能性があることです。たとえば、someMethod1()
が実行中 (および s をブロックsomeMethod2()
) であり、それが終了しようとしているときに、別のスレッドがやってきて を呼び出しますsomeMethod1()
。それは問題なく進行し、終了するとすぐに別のスレッドが開始someMethod1()
されます。このシナリオでsomeMethod2()
は、実行する機会はありません。これは、実際には上記のコードの直接のバグではありません。これはまさに設計ニーズの問題であり、優れたソリューションが積極的に解決する必要がある問題です。公正なAbstractQueuedSynchronizerでこのトリックを実行できると思いますが、それは読者に任せた演習です。:)
最後に、意見を差し挟まざるを得ません。ConcurrentHashMap
操作が非常に高速であることを考えると、両方のメソッドに単一のミューテックスを配置して、それを終了するだけの方がよい場合があります。そうです、スレッドは invoke をキューに入れる必要がありますsomeMethod1()
が、各スレッドはそのターンを非常に迅速に終了します (したがって、他のスレッドを続行させます)。それは問題ではないはずです。