java - ReentrantLock 与 CompletableFuture

标签 java multithreading locking completable-future reentrantlock

在 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
  • 如果当前线程已经持有锁,则持有计数加一,并且该方法立即返回
  • 如果锁被另一个线程持有,则出于线程调度目的,当前线程将被禁用,并处于 hibernate 状态,直到获取锁,此时锁持有计数设置为 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 可能会使用新线程执行上述操作,或者(如果我的理解是正确的)它可能会使用已在使用的线程。如果发生第二种情况(被重用的线程已经获取了锁),那么我的锁不会暂停线程并等待锁,相反,它实际上可能会立即返回(看起来像是获取了锁)!

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

非常感谢您的建议!

最佳答案

除了concurrency tutorial评论里推荐的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” block 中的 lock(),然后是“finally” block 中的 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()
     }
   }
 }

关于java - ReentrantLock 与 CompletableFuture,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59732830/

相关文章:

c++ - 锁定 vs (try_lock, sleep, repeat) 性能

python - 向 Python 线程发送参数会阻塞其他线程

java - CompletableFuture then 异常后撰写

java - 执行某些代码时,我在 android studio 中的应用程序崩溃

java - 如何从迭代器显示记录

c - 如何在现代多核/多插槽机器上扩展 TCP 监听器

具有稳定自动增量的 MySQL 原子插入(如果不存在)

c# - 为什么我们使用非静态属性来锁定非静态字段?

java - Android:枚举与静态最终整数?

Java:文件读取器、按定界符分隔的字符串分隔符帮助