我总是很困惑。有人能解释一下重入在不同背景下的含义吗?你为什么要使用“重入者”与“不可重入者”?
比如说,p线程(posix)锁定原语,它们是否是可重入的?使用它们时应该避免哪些陷阱?
互斥是可重入的吗?
发布于 2009-08-21 14:25:54
可重入锁
可重入锁是一个进程可以多次声明锁而不阻塞自身的锁。在不容易跟踪您是否已经抓起锁的情况下,它是有用的。如果一个锁是不可重入的,你可以抓住这个锁,然后当你再次抓住它的时候阻塞它,有效地锁定你自己的进程。
一般情况下,可重入性是代码的一个属性,在代码执行过程中,如果代码被调用,则它没有中央可变状态。这样的调用可以由另一个线程执行,也可以由代码本身内部的执行路径递归执行。
如果代码依赖于可以在其执行过程中更新的共享状态,那么它就不是可重入者,至少如果该更新可能破坏它的话。
--可重入锁用例
可重入锁的应用程序示例(有些是通用的和人为的)可能是:
这种情况的一个例子是Dijkstra算法的一个简单实现,其优先级队列实现为二进制堆,或者使用简单的链表作为队列进行宽度优先搜索。在这些情况下,扫描队列以查找现有的插入是O(N),您可能不希望在每次迭代中都这样做。
在这种情况下,跟踪您已经获得的锁是很昂贵的。假设您想要在节点级别执行锁定,则重新进入锁定机制可以减轻判断您以前是否访问过某个节点的需要。您可以盲目地锁定节点,也许在弹出队列后将其解锁。
可重入互斥体
一个简单的互斥不能重新进入,因为在给定的时间,只有一个线程可以在关键部分。如果您抓取互斥对象,然后再次尝试抓取它,那么一个简单的互斥体就没有足够的信息来告诉谁之前持有它。要递归地这样做,您需要一个机制,其中每个线程都有一个令牌,这样您就可以知道是谁抓取了互斥对象。这使得互斥机制更昂贵,所以您可能不想在所有情况下都这样做。
IIRC POSIX线程API确实提供了可重入和非重入互斥的选项。
发布于 2009-08-21 14:33:54
可重入锁允许您编写一个方法M,它将一个锁放在资源A上,然后递归地调用M,或者从已经持有A锁的代码中调用M。
使用非重入锁,您需要两个版本的M,一个锁的和一个没有锁的,并需要额外的逻辑来调用正确的一个。
发布于 2014-03-05 12:35:03
这个教程很好地描述了重入锁。
本教程中的示例比遍历图的答案少得多。在非常简单的情况下,重入锁很有用。
https://stackoverflow.com/questions/1312259
复制相似问题