java - 维护线程安全,同时防止可能发生同步回调的死锁

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

最佳答案

不确定是否完全实现了您想要实现的目标,但也许这就是您正在寻找的东西?

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

关于java - 维护线程安全,同时防止可能发生同步回调的死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45382932/

相关文章:

c# - 意外的异步/等待行为

python - 如何将协程添加到正在运行的 asyncio 循环中?

javascript - 在JS中,如何捕获用户自定义函数异步调用抛出的错误?

java - 如何在 recyclerview 中左右两个方向进行无限滚动?

java - 服务器到 Firebase HTTP POST 结果为响应消息 200

java - 服务数量对应用效率的影响

wpf - WPF在不同线程中创建多个窗口

iphone - 为什么当另一个线程正在运行时 NSTimer 会被阻塞?

java - 生成相关数字

java - Android 异步任务 ArrayList 操作导致 onDraw 中 IndexOutOfBounds