C: How do you declare a recursive mutex with POSIX threads?
I am a bit confused 开发者_高级运维on how to declare a recursive mutex using pthread. What I try to do is have only one thread at a time be able to run a piece of code(including functions) but after scepticism I figured out that the use of mutexes would not work and that instead I should use recursive mutexes. Here is my code:
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
So what I try to do is just read/remove from the queue serially.
The thing is that there isn't any example out there on how to declare recursive mutexes. Or there maybe a few but they don't compile for me.
The code from Michael Foukarakis is almost good but he initializes the mutex twice which leads to undefined behavior. It should just be:
pthread_mutex_t Mutex;
pthread_mutexattr_t Attr;
pthread_mutexattr_init(&Attr);
pthread_mutexattr_settype(&Attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&Mutex, &Attr);
I actually use this code in production, and I know it works correctly on Linux, Solaris, HP-UX, AIX, Mac OSX and FreeBSD.
You also need to add proper linker flag to compile this:
AIX, Linux, FreeBSD:
CPLATFORM += -pthread
mingw32:
LDFLAGS += -lpthread
To create a recursive mutex, you can either use:
#include <pthread.h>
/* Don't forget to check the return value! */
int pthread_mutexatttr_settype(pthread_mutexattr_t *attr,
int type);
where type is PTHREAD_MUTEX_RECURSIVE
, or an initialiser.
For example:
/* ..or PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP */
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutexattr_t mta;
or alternatively, initialize at runtime (don't do both, it's undefined behaviour):
pthread_mutexattr_init(&mta);
/* or PTHREAD_MUTEX_RECURSIVE_NP */
pthread_mutexattr_settype(&mta, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&mutex, &mta);
On Linux (but this is non portable to other systems), if the mutex is a global or static variable, you could initialize it like
static pthread_mutex_t recmutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
(and by the way, the example is from pthread_mutex_init(3)
man pages!)
You need to add mutex attributes when creating the mutex.
Call pthread_mutexattr_init
, then pthread_mutexattr_settype
with PTHREAD_MUTEX_RECURSIVE
then use these attributes with pthread_mutex_init
. Read man pthread_mutexattr_init
for more info.
精彩评论