【发布时间】:2012-07-19 19:24:22
【问题描述】:
我来自 Java,所以我熟悉同步而不是互斥锁。 我想知道 pthread_mutex_t 是否也是可重入的。如果没有,还有其他机制吗?
谢谢
【问题讨论】:
-
如果您需要可重入互斥锁,您的程序通常会出现问题。
标签: c++ c linux multithreading
我来自 Java,所以我熟悉同步而不是互斥锁。 我想知道 pthread_mutex_t 是否也是可重入的。如果没有,还有其他机制吗?
谢谢
【问题讨论】:
标签: c++ c linux multithreading
这取决于互斥体类型,默认情况下不进行检查,并且尝试在同一线程中多次锁定它会导致未定义的行为。阅读它here。
您可以创建PTHREAD_MUTEX_RECURSIVE 类型的互斥体,以便能够递归锁定它,这是通过向pthread_mutex_init 提供具有所需互斥体类型的pthread_mutexattr_t 来完成的
【讨论】:
pthread_mutex_lock 的信号处理程序调用pthread_mutex_lock 会调用未定义的行为。然而,可以以可重入的方式实现pthread_mutex_lock;有关如何完成的示例,请参见我在 musl libc 中的实现。关键细节是单个原子操作必须将互斥体从未锁定状态转换为 lock-with-count-1 状态。
根据the manual,可以将互斥对象声明为PTHREAD_MUTEX_RECURSIVE:
如果互斥锁类型是 PTHREAD_MUTEX_RECURSIVE,那么互斥锁应该 维护锁计数的概念。当一个线程成功 第一次获取互斥锁,锁计数设置为 一。每次线程重新锁定此互斥体时,锁定计数应为 加一。每次线程解锁互斥锁时,锁 计数应减一。当锁计数达到零时, 互斥锁应可供其他线程获取。如果一个 线程尝试解锁尚未锁定的互斥锁或互斥锁 解锁,返回错误。
【讨论】:
默认情况下,pthread_mutex 不是递归的,但有一种方法可以将其初始化为递归:
pthread_mutexattr_t Attr;
pthread_mutexattr_init(&Attr);
pthread_mutexattr_settype(&Attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&_mutex, &Attr);
【讨论】: