我从各种来源( 1、 2 )听说应该避免使用递归互斥锁,因为这可能是黑客或糟糕设计的标志。但是,有时我认为它们可能是必要的。鉴于此,以下是递归互斥锁的合适用例吗?
// main.c
// gcc -Wall -Wextra -Wpedantic main.c -pthread
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif /* _GNU_SOURCE */
#include <assert.h>
#include <pthread.h>
#include <stdlib.h>
typedef struct synchronized_counter
{
int count;
pthread_mutex_t mutex;
pthread_mutexattr_t mutexattr;
} synchronized_counter;
synchronized_counter* create_synchronized_counter()
{
synchronized_counter* sc_ptr = malloc(sizeof(synchronized_counter));
assert(sc_ptr != NULL);
sc_ptr->count = 0;
assert(pthread_mutexattr_init(&sc_ptr->mutexattr) == 0);
assert(pthread_mutexattr_settype(&sc_ptr->mutexattr,
PTHREAD_MUTEX_RECURSIVE) == 0);
assert(pthread_mutex_init(&sc_ptr->mutex, &sc_ptr->mutexattr) == 0);
return sc_ptr;
}
void synchronized_increment(synchronized_counter* sc_ptr)
{
assert(pthread_mutex_lock(&sc_ptr->mutex) == 0);
sc_ptr->count++;
assert(pthread_mutex_unlock(&sc_ptr->mutex) == 0);
}
int main()
{
synchronized_counter* sc_ptr = create_synchronized_counter();
// I need to increment this counter three times in succesion without having
// another thread increment it in between. Therefore, I acquire a lock
// before beginning.
assert(pthread_mutex_lock(&sc_ptr->mutex) == 0);
synchronized_increment(sc_ptr);
synchronized_increment(sc_ptr);
synchronized_increment(sc_ptr);
assert(pthread_mutex_unlock(&sc_ptr->mutex) == 0);
return 0;
}
编辑:
我想用一个简单的例子来问这个问题,但也许它太简单了。这就是我想象的更现实的场景:我有一个堆栈数据结构,可以被多个线程访问。特别是,有时一个线程会从堆栈中弹出 n 个元素,但它必须一次全部完成(中间没有另一个线程从堆栈中压入或弹出)。设计问题的关键是我是否应该让客户端自己管理使用非递归互斥锁锁定堆栈,或者让堆栈提供同步的、简单的方法以及递归互斥锁,客户端可以使用这些方法进行多个原子事务也是同步的。