Ich habe eine API wie folgt, wobei Baz
ist die Worker-Implementierung. Diese Bar
muss Thread-sicher sein, und dies wird schwierig, wenn Sie mit Baz Callbacks interagieren.Thread-Sicherheit beibehalten, während Deadlock von möglicherweise synchronen Rückruf verhindert
Die aktuelle Baz-Instanz muss im Callback referenziert werden (das für einen Worker-Thread oder synchron aufgerufen werden kann). Die Kommentare sollten das Problem zeigen:
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();
}
});
}
}
Gibt es eine gute Möglichkeit, diese Arbeit richtig zu machen, während auch nicht ein Deadlock verursacht?
Edit: kurz und bündig:
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();
}
}
Die Baz-Zuweisung muss jedoch im Callback sein. –
bearbeitet, um zu klären. –
Warum sollte im Rückruf darauf verwiesen werden? Der Code, den ich gepostet habe, stellt sicher, dass baz nicht reinitet wird, bis der Rückruf fertig ist. –