正在初始化pthread互斥

Initializing pthread mutexes

本文关键字:互斥 pthread 初始化      更新时间:2023-10-16

根据文档,互斥可以通过两种方式初始化:

使用init函数:

pthread_mutex_t theMutex;
pthread_mutex_init(&theMutex, NULL);

使用初始化宏:

pthread_mutex_t result = PTHREAD_MUTEX_INITIALIZER;

关于后者,文件中写道:

在默认互斥属性合适的情况下,可以使用宏PTHREAD_mutex_INITIALIZER初始化静态分配的互斥。该效果应等效于通过调用pthread_mutex_init()进行动态初始化,参数attr指定为NULL,但不执行错误检查。

这是否意味着它只能用于静态变量而不能用于局部变量?

C++特定

我想使用以下"工厂功能":

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

因为它允许我在C++初始化器列表中初始化互斥对象,如下所示:

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

这个有效吗?(顺便说一句,在实践中它是有效的。Valgrind也没有抱怨。)

更新

如果我正确理解了文档,那么这应该是可以的:

#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}};

事实证明,同一个互斥对象被创建了三次。我在这里做错了什么?

Re"原来创建了三次相同的互斥对象。我做错了什么?"

你在这里没有做错什么。同一个互斥对象没有创建三次。看起来您正在将0x32AABA7解释为一个地址。事实并非如此。它本质上是一个枚举值,但有汉明代码保护,(a)使其安全,(b)使其模糊。这里有三个不同的互斥对象。

Standard不允许按值复制互斥对象或按值返回互斥对象。看见http://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_mutex_init.html,明确谈到这一点的段落,称"IEEE Std 1003.1-2001没有定义这种类型的赋值或相等[ppthread_mutex_t]"

pthread_mutex的最接近的亲属WIN32 CriticalSection绝对不可复制,也不可按值返回。所以你的API无论如何都是不可移植的。

我建议不要按值复制(返回)互斥体,即使您可以测试它并且它有效。

请注意,初始化互斥锁与复制已初始化的互斥锁不同。

仅仅因为你能做到,并不意味着你应该做到。

文档明确规定在运行时使用pthread_mutex_init,而另一个宏用于静态分配的互斥,我看不出有任何理由不这样做

您的GetFastNativeMutex决不是一个工厂函数。它总是返回同一互斥对象的副本,工厂的目的是抽象分配和创建一个新对象,而不是一直重用同一个对象。所以,不,这对于任何不能通过使用与全局变量相同的互斥来实现的用法都是无效的。

引用自这里:

引用的副本的结果对的调用中的互斥pthread_mutex_lock(),pthread_mutex_trylock(),pthread_mutex_unlock(),以及pthread_mutex_destroy()未定义

如果所有myMutex实例都应该共享相同的POSIX互斥,那么它"有效"。您当前有一个互斥对象,而不是每个MyClass对象有一个。这肯定不是你想要的,不是吗?