POSIX允许互斥锁递归.这意味着同一个线程可以锁定相同的互斥锁两次并且不会死锁.当然它还需要解锁两次,否则没有其他线程可以获得互斥锁.并非所有支持pthread的系统都支持递归互斥锁,但如果它们想要符合POSIX,则必须使用.
其他API(更高级别的API)通常也提供互斥锁,通常称为锁定.一些系统/语言(例如Cocoa Objective-C)提供递归和非递归互斥体.有些语言也只提供一种或另一种语言.例如,在Java中,互斥锁总是递归的(同一个线程可能在同一个对象上"同步"两次).根据它们提供的其他线程功能,没有递归互斥体可能没有问题,因为它们可以很容易地自己编写(我已经在更简单的互斥/条件操作的基础上自己实现了递归互斥锁).
我真的不明白:什么是非递归互斥量有用?如果它锁定相同的互斥锁两次,为什么我想要一个线程死锁?即使是可以避免这种情况的高级语言(例如测试它是否会死锁并抛出异常)通常也不会这样做.他们会让线程陷入僵局.
这只适用于我意外锁定它两次并且只解锁一次的情况,并且在递归互斥锁的情况下,它会更难找到问题,所以相反我立即死锁以查看错误锁定出现在哪里?但是我不能在解锁时返回一个锁定计数器并且在某种情况下,我确定我释放了最后一个锁并且计数器不为零,我可以抛出异常或记录问题吗?或者是否有其他更有用的非递归互斥体用例我看不到?或者它可能只是性能,因为非递归互斥体可能比递归互斥体略快?但是,我对此进行了测试,差异确实不大.
我理解递归互斥锁允许互斥锁被锁定不止一次而不会陷入死锁,应该解锁相同的次数.但是在什么特定情况下你需要使用递归互斥体?我在寻找设计/代码级别的情况.
我对如何使用pthread声明递归互斥锁感到困惑.我尝试做的是一次只有一个线程能够运行一段代码(包括函数)但是在怀疑之后我发现使用互斥量不起作用而我应该使用递归互斥锁.这是我的代码:
pthread_mutex_lock(&mutex); // LOCK
item = queue_peek(queue); // get last item in queue
item_buff=item; // save item to a buffer
queue_removelast(queue); // remove last item from queue
pthread_mutex_unlock(&mutex); // UNLOCK
Run Code Online (Sandbox Code Playgroud)
所以我尝试做的只是串行读取/删除队列.
问题在于,没有任何关于如何声明递归互斥体的例子.或者可能有一些,但他们不为我编译.
我见过有些人讨厌recursive_mutex:
http://www.zaval.org/resources/library/butenhof1.html
但是在考虑如何实现一个线程安全的类(互斥保护)时,我觉得很难证明每个应该受互斥保护的方法都是互斥保护的,并且互斥锁最多被锁定一次.
因此,对于面向对象的设计,应该std::recursive_mutex是默认的并且std::mutex在一般情况下被视为性能优化,除非它仅在一个地方使用(仅保护一个资源)?
为了说清楚,我说的是一个私人非静态互斥体.因此每个类实例只有一个互斥锁.
在每个公共方法的开头:
{
std::scoped_lock<std::recursive_mutex> sl;
Run Code Online (Sandbox Code Playgroud) 你可以结合std::recursive_mutex使用std::condition_variable,意思是做这样的事情:
std::unique_lock<std::recursive_mutex> lock(some_recursive_mutex)
some_condition_var.wait(lock);
Run Code Online (Sandbox Code Playgroud)
如果不允许,为什么不呢?
我正在使用VC++ 11.
根据这个,unique_lock可以通过声明a来实现递归锁定std::unique_lock<std::recursive_mutex>,实际上编译很好.
但是,通过检查unique_lock不遵循的代码(gcc 4.8.2和4.9.0)_Mutex.lock,而不是实现锁定方法本身:
void
lock()
{
if (!_M_device)
__throw_system_error(int(errc::operation_not_permitted));
else if (_M_owns)
__throw_system_error(int(errc::resource_deadlock_would_occur));
else
{
_M_device->lock();
_M_owns = true;
}
Run Code Online (Sandbox Code Playgroud)
显然,这可以防止互斥锁的递归锁定,实际上尝试递归锁定会抛出resource_deadlock_would_occur异常.
我在这里遗漏了什么,这是一个错误,还是unique_lock的文档错了?
TIA!
pthreads 是否支持任何允许您查询递归互斥锁被锁定次数的方法?
我有一个案例,我的算法的决定是基于共享的深度std::recursive_mutex.
#include <iostream>
#include <mutex>
#include <thread>
int g_i = 0;
std::recursive_mutex g_i_mutex;
void bar() {
std::lock_guard<std::recursive_mutex> lock(g_i_mutex);
switch (get_counter(g_i_mutex)) { // some way to find the number of owners
case 1: std::cout << "depth 1\n"; break;
case 2: std::cout << "depth 2\n"; break;
default:;
}
}
void foo() {
std::lock_guard<std::recursive_mutex> lock(g_i_mutex);
std::cout << "hello\n";
bar();
}
int main() {
foo(); //print hello then depth 2
bar(); //print depth 1
}
Run Code Online (Sandbox Code Playgroud)
我已经读过递归互斥锁持有某种使用计数,并且每次调用锁定/解锁时它们会增加和减少它,有没有办法访问这些信息?
我正在尝试使用递归QMutex,我读了QMutex类参考,但我不明白该怎么做,有人可以举个例子吗?我需要一些方法来锁定QMutex,可以在调用lock方法之后或之前解锁.如果递归互斥不是这样的方式还有其他方法吗?
我正在学校实验室工作,我们被指示为计数程序创建一个递归互斥锁.我写了一些代码(不起作用),但我认为这主要是因为我不明白使用递归互斥锁的真正想法.任何人都可以详细说明递归互斥锁应该做什么/看起来像什么?
一般注意:我不是要求答案,只是澄清一下递归互斥锁应该做什么.
此外,如果有人好奇,这里是这需要的代码.我正在编辑/实现的代码是recmutex.c.
recmutex.h
#include <pthread.h>
/*
* The recursive_mutex structure.
*/
struct recursive_mutex {
pthread_cond_t cond;
pthread_mutex_t mutex; //a non-recursive pthread mutex
pthread_t owner;
unsigned int count;
unsigned int wait_count;
};
typedef struct recursive_mutex recursive_mutex_t;
/* Initialize the recursive mutex object.
*Return a non-zero integer if errors occur.
*/
int recursive_mutex_init (recursive_mutex_t *mu);
/* Destroy the recursive mutex object.
*Return a non-zero integer if errors occur.
*/
int recursive_mutex_destroy (recursive_mutex_t *mu);
/* The recursive mutex object referenced by mu …Run Code Online (Sandbox Code Playgroud)