保持线程安全,同时防止可能同步回调的死锁

时间:2017-07-28 21:53:03

标签: java multithreading asynchronous thread-safety synchronous

我有一个类似以下的API,其中Baz是工作者实现。 这个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();
      }
    });
  }
}

是否有一种很好的方法可以正常工作,同时又不会造成死锁?

编辑:更简洁:

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();
  }
}

1 个答案:

答案 0 :(得分:0)

不确定完全得到你想要达到的目标,但也许这就是你要找的东西?

final class Bar {
    final Lock lock = new ReentrantLock();
    Baz baz = new Baz();

    void run() {
        if (!lock.tryLock()) {
            return;
        }
        try {
            CountdownLatch callbackFlag = new CountdownLatch(1);
            baz.run(new Baz.Callback() {
                @Override
                public void done() {
                    callbackFlag.countDown();
                }
            });
            try {
                callbackFlag.await(); // better use overloaded method with max timeout waiting. you don't probably want to wait forever
                baz = new Baz(); // do you really want to reinit Baz on each execution?
            } catch (InterruptedException e) {
                // decide what you want to happen here
            }
        } finally {
            lock.unlock();
        }
    }
}