我总是很困惑。有人会解释Reentrant在不同上下文中的含义吗?以及为什么要使用可重入与非可重入?

说pthread(posix)锁定原语,它们是否可重入?使用它们时应避免哪些陷阱?

互斥体是可重入的吗?

最佳答案

重新进入锁定

可重入锁是一种过程可以多次声明该锁而又不会对其自身进行阻塞的锁。在难以跟踪您是否已经捕获锁的情况下,此功能很有用。如果某个锁是不可重入的,则可以获取该锁,然后在再次获取时阻塞,从而有效地死锁了自己的进程。

通常,重入是代码的属性,其中没有中央可变状态,如果在执行代码时调用该代码,则该可变状态可能会损坏。这样的调用可以由另一个线程进行,也可以由源自代码本身内部的执行路径递归地进行。

如果代码依赖于可以在执行过程中进行更新的共享状态,则它不是可重入的,至少不可以,如果该更新可能破坏它。

用于重入锁定的用例

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

  • 您进行了一些计算,其中涉及遍历图形的算法(可能带有循环)。由于循环或到同一节点的多条路径,遍历可能会多次访问同一节点。
  • 数据结构可以并发访问,并且由于某种原因可能会被另一个线程更新。您需要能够锁定单个节点以应对由于竞争条件而导致的潜在数据损坏。由于某种原因(也许是性能),您不想全局锁定整个数据结构。
  • 您的计算无法保留有关您访问过哪些节点的完整信息,或者您使用的数据结构不允许快速回答“以前曾来过这里”的问题。这种情况的一个示例是Dijkstra算法的简单实现,其中优先级队列实现为二进制堆,或者使用简单链接列表作为队列的广度优先搜索。在这些情况下,扫描队列中是否存在现有插入为O(N),并且您可能不想在每次迭代中都这样做。

  • 在这种情况下,跟踪您已经获得的锁是很昂贵的。假设您想在节点级别进行锁定,可重入锁定机制将减轻您判断以前是否访问过节点的需要。您可以盲目地锁定节点,也可以在将其从队列中弹出后将其解锁。

    重新进入互斥锁

    简单的互斥锁不能重入,因为在给定的时间,关键区中只能有一个线程。如果您捕获互斥锁然后尝试再次获取它,那么简单的互斥锁将没有足够的信息来告诉谁以前握住了它。要递归地执行此操作,您需要一种机制,其中每个线程都有一个 token ,以便您可以知道谁捕获了互斥量。这使得互斥锁机制有些昂贵,因此您可能不想在所有情况下都这样做。

    IIRC POSIX线程API确实提供了可重入和不可重入互斥的选项。

    关于multithreading - 一般而言,重入锁和概念是什么?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/1312259/

    10-09 02:53