带有 CompletableFuture 的 ReentrantLock

ReentrantLock with CompletableFuture

在 CompletableFuture 的世界之前,如果我想锁定一个变量,我可以这样做:

  private ReentrantLock myLock = new ReentrantLock();
  private List<UUID> myLockableList = new ArrayList<>();

  public void doStuff()
  {
    try
    {
      myLock.lock();
      myLockableList.clear();
    }
    finally
    {
      if (myLock.isLocked())
      {
        myLock.unlock();
      }
    }
  }

(显然,这是一个非常简化的示例,我也有其他方法尝试对 myLockableList 进行操作)。

根据 ReentrantLock,会发生 3 种情况中的 1 种:

一切都很好,正是我所期望的行为方式:如果在同一个线程中工作,我应该知道我是否锁定了资源,如果另一个线程锁定了资源,我想等到它可用。

输入 CompletableFutures...

  private ReentrantLock myLock = new ReentrantLock();
  private List<UUID> myLockableList = new ArrayList<>();

  public CompletionStage<Void> doStuff()
  {
    return CompletableFuture.runAsync(() -> {
      try
      {
        myLock.lock();
        myLockableList.clear();
      }
      finally
      {
        if (myLock.isLocked())
        {
          myLock.unlock();
        }
      }
    });
  }

我希望 CompletableFuture 的行为是一样的。但是,CompletableFuture 可能会使用新线程执行上述操作,或者(如果我的理解是正确的)它可能会使用已在使用的线程。如果发生第二种情况(被重用的线程已经获得了锁),那么我的锁不会暂停线程并等待锁,相反,它实际上可能 return 立即(看起来它已经获得了锁)!

我似乎无法在文档中找到明确的答案。我是否正确理解了情况?如果是这样,我们应该如何在使用 CompletableFuture 时锁定资源?

非常感谢任何建议!

此外 concurrency tutorial recommended in the comments, the Javadoc for ReentrantLock 还提供了值得一读的重要信息。

这个,例如:

A ReentrantLock is owned by the thread last successfully locking, but not yet unlocking it.

你的例子使用了 isLocked(),Javadoc 说你不应该这样做:

This method is designed for use in monitoring of the system state, not for synchronization control.

最后,Javadoc 包含一个很好的用法示例,显示 "try" 块中的 lock() 后跟 "finally" 块中的 unlock()

It is recommended practice to always immediately follow a call to lock with a try block, most typically in a before/after construction such as:

 class X {
   private final ReentrantLock lock = new ReentrantLock();
   // ...

   public void m() {
     lock.lock();  // block until condition holds
     try {
       // ... method body
     } finally {
       lock.unlock()
     }
   }
 }