Подтвердить что ты не робот

C: Как вы объявляете рекурсивный мьютекс с потоками POSIX?

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

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

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

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

где type PTHREAD_MUTEX_RECURSIVE.

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

Пример:

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

или, альтернативно, инициализируйте во время выполнения (не выполняйте оба режима: undefined):

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

pthread_mutex_init(&mutex, &mta);

Ответ 3

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

static pthread_mutex_t recmutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;

(и, кстати, пример из pthread_mutex_init(3) man-страниц!)

Ответ 4

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

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