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

Инициализация мьютексов pthread

В соответствии с документацией мьютекс можно инициализировать двумя способами:

Использование функции init:

pthread_mutex_t theMutex;
pthread_mutex_init(&theMutex, NULL);

Использование макроса инициализатора:

pthread_mutex_t result = PTHREAD_MUTEX_INITIALIZER;

О последнем говорится в документации:

В случаях, когда атрибуты mutex по умолчанию подходят, макрос PTHREAD_MUTEX_INITIALIZER можно использовать для инициализации взаимно устаревших мьютексов. Эффект должен быть эквивалентен динамической инициализации вызовом pthread_mutex_init() с параметром attr, указанным как NULL, за исключением того, что не выполняются проверки ошибок.

Означает ли это, что его можно использовать только для статических переменных, а не для локальных переменных?

С++ Конкретный

Я хотел использовать следующую функцию factory:

static pthread_mutex_t GetFastNativeMutex()
{
    static pthread_mutex_t result = PTHREAD_MUTEX_INITIALIZER;
    return result;
}

Поскольку это позволило бы мне инициализировать мьютексы в списке инициализаторов С++ следующим образом:

MyClass() : myMutex(GetFastNativeMutex()) {}

Это действительно? (Кстати, на практике это работает. Valgrind также не жалуется.)

Update

Если я правильно понял документацию, это должно быть нормально:

#include <pthread.h>

static pthread_mutex_t m0 = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t m1 = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t m2 = PTHREAD_MUTEX_INITIALIZER;

Однако при просмотре вывода препроцессора (используя gcc -E main.cpp) я вижу следующее:

static pthread_mutex_t m0 = {0x32AAABA7, {0}};
static pthread_mutex_t m1 = {0x32AAABA7, {0}};
static pthread_mutex_t m2 = {0x32AAABA7, {0}};

Оказывается, что три раза был создан один и тот же мьютекс. Что я здесь делаю неправильно?

4b9b3361

Ответ 1

Re "Оказывается, три раза был создан один и тот же мьютекс. Что я здесь делаю неправильно?"

Ты здесь ничего не делаешь. Тот же мьютекс не был создан три раза. Похоже, вы интерпретируете этот адрес 0x32AAABA7. Это не так. Это, по сути, значение перечисления, но с защитой кода Хэмминга (а) сделать его безопасным и (б) сделать его неясным. У вас есть три различных взаимных обозначения.

Ответ 2

Стандарт не позволяет копировать мьютексы по значению или возвращать их по значению. См. http://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_mutex_init.html, абзац, который явно говорит об этом, говоря: "IEEE Std 1003.1-2001 не определяет назначение или равенство для этого типа [pthread_mutex_t]"

Ближайший родственник pthread_mutex, WIN32 CriticalSection, абсолютно не копируется и не возвращается по значению. Таким образом, ваш API будет очень непереносимым.

Я рекомендую не копировать (возвращать) мьютекс по значению, даже вы можете его протестировать, и он работает.

Обратите внимание, что инициализация мьютекса отличается от копирования уже инициализированных мьютексов.

Ответ 3

Просто потому, что вы можете это сделать, это не значит, что вы должны.

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

Ответ 4

Ваш GetFastNativeMutex не является функцией factory. Он всегда возвращает копию одного и того же мьютекса, точка factory - это абстрактное выделение и создание нового объекта, а не повторное использование одного и того же. Таким образом, нет, это недействительно для любого использования, которое не было бы сделано с использованием того же мьютекса, что и глобальная переменная.

Цитата из здесь:

Результат обращения к копиям мьютекс в вызовах pthread_mutex_lock(), pthread_mutex_trylock(), pthread_mutex_unlock() и pthread_mutex_destroy() - undefined

Ответ 5

Он "работает", если все экземпляры myMutex должны использовать один и тот же мьютез POSIX. В настоящее время у вас есть один мьютекс, а не один объект MyClass. Это, безусловно, не то, что вы хотите, не так ли?