Java 为什么要递归获取(可重入)锁?

Java 为什么要递归获取(可重入)锁?,java,multithreading,recursion,reentrantlock,Java,Multithreading,Recursion,Reentrantlock,ReentrantLock允许线程递归地获取相同的锁,以便在连续锁定/解锁时增加和减少锁计数。而锁计数必须在释放到其他线程之前递减为零 为什么或者在什么情况下我会编写代码来递归地获取锁 我在拥有这个特性中看到的唯一一点是使我们能够方便地编写递归代码,其中一个方法(在其执行过程中获得锁)被递归调用 是否存在线程递归/重复获取锁可能有用的其他情况 澄清问题: 请忽略重入的锁。恰好递归性是由可重入锁提供的 我指的是锁的递归特性 请不要回答为什么使用重入锁 请不要回答“递归性不是可重入锁的主要特性”

ReentrantLock允许线程递归地获取相同的锁,以便在连续锁定/解锁时增加和减少锁计数。而锁计数必须在释放到其他线程之前递减为零

为什么或者在什么情况下我会编写代码来递归地获取锁

我在拥有这个特性中看到的唯一一点是使我们能够方便地编写递归代码,其中一个方法(在其执行过程中获得锁)被递归调用

是否存在线程递归/重复获取锁可能有用的其他情况

澄清问题:
  • 请忽略重入的锁。恰好递归性是由可重入锁提供的
  • 我指的是锁的递归特性
  • 请不要回答为什么使用重入锁
  • 请不要回答“递归性不是可重入锁的主要特性”
  • 我想知道什么情况需要递归获取锁,而不管锁是否可重入

    • 最好搜索:

      可重入锁定的用例: 重入锁应用程序的一个(有些通用和人为)示例可能是:

    • 有一些计算涉及一个遍历 图形(可能包含循环)。遍历可以访问同一个对象 由于循环或到的多条路径,节点不止一次 同一节点

    • 数据结构受并发访问的约束,可以 由于某种原因更新,可能是由另一个线程更新的。你需要 能够锁定单个节点以处理潜在的数据损坏 由于比赛条件。出于某种原因(也许是性能)你 不希望全局锁定整个数据结构

    • 您无法保留有关哪些节点的完整信息 您已经访问过,或者您正在使用的数据结构不允许 “我以前来过这里吗”的问题需要快速回答

    • 这种情况的一个例子是 Dijkstra算法,优先级队列作为二进制实现 使用简单链表作为队列的堆或广度优先搜索。 在这些情况下,扫描队列以查找现有插入是O(N) 您可能不希望在每次迭代中都这样做

    • 在这种情况下,跟踪您已经锁定的锁 收购成本很高。假设要在节点上执行锁定 a级重入锁定机制减少了告知的需要 您以前是否访问过节点。你可以盲目地锁上钥匙
      节点,可能在您将其从队列中弹出后将其解锁。

      很抱歉编辑您的答案,因为我需要按项目编号引用这些项目。项目1:如果遍历必须是原子的,用单个锁锁定整个树/图不是更好吗?通过单独锁定节点以原子方式遍历一棵树难道不会产生死锁的可怕风险吗?第2项:当我需要获取三个节点来完成一个原子操作时,我会首先获取这些节点。如果我无法获得完整的节点集,我将退出并释放所有节点。如果它达到一种情况,即我无法跟踪我需要以原子方式获取的节点,因此由于算法的复杂性,我可能会获取它两次-该算法应该被禁止,除非它是由超人、奥特曼或美国队长编写的。第4项:Dijkstra的算法需要锁定吗?我最近的项目,我们用粒度设计了图,这样我们可以按区域锁定图。我们只需锁定图形的整个区域。因此,我们最多锁定了三个区域,没有两次获得相同锁定的风险。正确地设计一个图比随意地使用一个优雅的容易死锁的锁定算法更安全。