3
Baz
はワーカーの実装で、次のようなAPIがあります。 このBar
はスレッドセーフである必要があります。これは、Bazのコールバックとやりとりするときには厄介です。デッドロックが同期コールバックを起こさないようにスレッドセーフを維持
現在のbazインスタンスは、コールバック(ワーカースレッド上で呼び出すことも同期して呼び出すこともできます)で参照する必要があります。 コメントは、問題が表示されるはずです:
final class Bar {
final Lock lock = new ReentrantLock();
Baz baz; // Guarded by lock.
void run() { // Called by any thread.
lock.lock();
if (baz.isRunning()) {
lock.unlock();
return;
}
baz = new Baz();
// If it unlocks here, the next line may execute on the wrong Baz.
// If it doesn't unlock here, there will be a deadlock when done() is called synchronously.
// lock.unlock();
baz.run(new Baz.Callback() { // May be called synchronously or by Baz worker thread.
@Override
public void done() {
lock.lock();
baz = new Baz();
lock.unlock();
}
});
}
}
も、デッドロックが生じないながら正しく、この作品を作るための良い方法はありますか?
編集:もっと簡潔に:あなたが達成しようとしているものを得るcompletellyする
final class Foo {
final Lock lock = new ReentrantLock();
void run() {
lock.lock();
worker.enqueue(new Callback() {
@Override void complete() {
lock.lock(); // Could cause deadlock.
}
});
lock.unlock();
}
}
しかし、baz割り当てはコールバックにある必要があります。明確にするために –
が編集されました。 –
なぜコールバックで参照されるべきですか?私が投稿したコードは、コールバックが完了するまで、bazが再初期化されないようにします。もしも本当に必要ならば、 –