如何更改Windows互斥量的递归锁定行为?

9

Windows互斥锁似乎允许当前拥有锁的线程在尝试获取锁时再次获取(递归)。

但是,基于posix的pthread锁不允许这种行为。

是否有任何编译时宏或任何设置可以使Windows互斥锁的行为与pthread互斥锁相同?

4个回答

11

您无法改变Windows Mutexes是递归的这一事实。而虽然默认情况下Posix线程不是递归的,但您可以使用pthread_mutexattr_settype()PTHREAD_MUTEX_RECURSIVE标志来使其成为递归。

在Windows中锁定互斥对象实际上是一项相当昂贵的操作,最适合用于进程间同步。对于仅在单个进程内使用的互斥对象,通常使用关键节,但这些也是可重入的。正如nobugz所说,您需要使用一个信号量,初始化为1的最大计数,以获得非递归同步。

信号量对象就像一个特殊的计数器,可以在线程(或进程,如果创建共享)之间原子地增加和减少。通过创建一个最大计数为1的信号量,您可以获得所需的非递归行为。


关键区段可以从同一线程再次进入。http://msdn.microsoft.com/en-us/library/ms682608(VS.85).aspx - Chris Walton
谢谢你发现了那个小错误 - 我已相应地修正了答案。 - gavinb

9
只要你在Windows上编程,就避免重新实现其Mutex的行为。它被同一线程重入对于其定义的行为是绝对必要的。
没有线程亲和性的同步对象是一个计数为1的信号量。请使用CreateSemaphore()。
顺便说一下,你需要这种类型的行为非常奇怪。听起来你正在不适当地尝试在多个地方使用相同的同步对象。你可以使用信号量,但会失去并发潜力。考虑使用多个mutex代替。

实际上,我有一个与旧代码相关的问题,我想在不改变太多逻辑的情况下解决它。所以,想知道行为是否可以改变。我的代码应该在多个操作系统中工作,因此我希望行为在所有操作系统中保持一致。“听起来你正在尝试不适当地在多个位置使用相同的同步对象。” - 是的。这是负面情况。我只希望在所有操作系统中负面情况下的行为都是相同的。谢谢您的回复! - Jay
1
好的,使用boost信号量。跨平台且非可重入。 - Hans Passant
1
您可能希望使用非递归互斥锁来同步任务(例如实现N个任务之间的屏障)。此外,有很多理由认为递归互斥锁是有害的,应该避免使用。 - Jérôme Pouiller

2

我建议使用读写锁(也称为SRW)。与Windows互斥量不同,它们不是递归的。但像临界区一样,它们是轻量级的,如果它们是空闲的,就不会调用内核(基准测试)。


0

请查看'快速互斥锁'的文章。

这些类型的互斥锁不能递归获取。

当然,您需要了解如何在C中实现它们。


快速互斥支持是为驱动程序而设计的,而不是用户模式代码。 - gavinb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接