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
Итак, что я пытаюсь сделать, просто читайте/удаляйте из очереди поочередно.
Дело в том, что нет никакого примера, как объявить рекурсивные мьютексы. Или, может быть, несколько, но они не компилируются для меня.
Ответы
Ответ 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
.