C: Как вы объявляете рекурсивный мьютекс с потоками POSIX? - PullRequest
44 голосов
/ 12 августа 2011

Я немного запутался, как объявлять рекурсивный мьютекс с помощью 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

Итак, я пытаюсь последовательно читать / удалять из очереди.

Дело в том, что нет никакого примера, как объявлять рекурсивные мьютексы. Или, может быть, несколько, но они не компилируются для меня.

Ответы [ 4 ]

79 голосов
/ 01 ноября 2011

Код от Майкла Фукаракиса почти хорош, но он дважды инициализирует мьютекс, что приводит к неопределенному поведению.Это должно быть просто:

pthread_mutex_t Mutex;
pthread_mutexattr_t Attr;

pthread_mutexattr_init(&Attr);
pthread_mutexattr_settype(&Attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&Mutex, &Attr);

Я на самом деле использую этот код в производстве, и я знаю, что он корректно работает в Linux, Solaris, HP-UX, AIX, Mac OSX и FreeBSD.Вы также должны добавить правильный флаг компоновщика, чтобы скомпилировать это:

AIX, Linux, FreeBSD:
CPLATFORM += -pthread

mingw32:
LDFLAGS += -lpthread
16 голосов
/ 12 августа 2011

Чтобы создать рекурсивный мьютекс, используйте:

#include <pthread.h>
int pthread_mutexatttr_settype(pthread_mutexattr_t *attr,
                               int type);

где тип PTHREAD_MUTEX_RECURSIVE.

Не забудьте проверить возвращаемое значение!

Пример:

/* or PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP */
pthread_mutex_t       mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutexattr_t   mta;

или, альтернативно, инициализация во время выполнения (не выполняйте оба действия, это неопределенное поведение):

pthread_mutexattr_init(&mta);
/* or PTHREAD_MUTEX_RECURSIVE_NP */
pthread_mutexattr_settype(&mta, PTHREAD_MUTEX_RECURSIVE);

pthread_mutex_init(&mutex, &mta);
13 голосов
/ 28 октября 2011

В Linux (но это непереносимо в другие системы), если мьютекс является глобальной или статической переменной, вы можете инициализировать его как

static pthread_mutex_t recmutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;

(и, кстати, пример изpthread_mutex_init(3) человек страниц!)

2 голосов
/ 12 августа 2011

Вам необходимо добавить атрибуты мьютекса при создании мьютекса.

Вызовите pthread_mutexattr_init, затем pthread_mutexattr_settype с PTHREAD_MUTEX_RECURSIVE, затем используйте эти атрибуты с pthread_mutex_init. Прочитайте man pthread_mutexattr_init для получения дополнительной информации.

...