J'ai une API comme celle-ci, où Baz
est l'implémentation du worker. Ce Bar
doit être thread-safe, et cela devient compliqué lors de l'interaction avec les rappels de Baz.Maintenir la sécurité des threads tout en empêchant les interblocages dus à un éventuel rappel synchrone
L'instance baz actuelle doit être référencée dans le rappel (qui peut être appelé sur un thread de travail ou de manière synchrone). Les commentaires devraient montrer le problème:
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();
}
});
}
}
est-il un bon moyen de faire correctement ce travail tout en ne provoquant pas une impasse?
Edit: plus succinctement:
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();
}
}
L'affectation baz doit cependant être dans le rappel. –
édité pour clarifier. –
pourquoi devrait-il être référencé dans le rappel? le code que j'ai posté assure que baz n'est pas reinit jusqu'à ce que le callback soit terminé –