根据documentation,可以通过两种方式初始化互斥锁:
使用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,效果应等效于动态初始化,但不执行错误检查。
这是否意味着它只能用于静态变量而不能用于局部变量?
我想使用以下“工厂功能”:
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}};
事实证明,创建了三倍相同的互斥锁。我在这里做错了什么?
答案 0 :(得分:24)
Re“事实证明,创建了三倍相同的互斥锁。我在这里做错了什么?”
你在这里做错了什么。没有创建三次相同的互斥锁。看起来你正在将0x32AAABA7解释为一个地址。事实并非如此。它本质上是一个枚举值,但具有汉明码保护,以便(a)使其安全并且(b)使其模糊不清。这里有三个不同的互斥锁。
答案 1 :(得分:9)
标准版不允许按值复制互斥锁或按值返回互斥锁。请参阅http://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_mutex_init.html,明确谈到这一点的段落,说“IEEE Std 1003.1-2001没有为此类型定义赋值或相等[pthread_mutex_t]”
pthread_mutex,WIN32 CriticalSection的最近亲属绝对不可复制,不能按值返回。因此,无论如何,您的API将非常不便携。
我建议不要按值复制(返回)互斥锁,即使你可以对其进行测试也可以正常工作。
请注意,初始化互斥锁与复制已初始化的互斥锁不同。
答案 2 :(得分:4)
仅仅因为你能做到,并不意味着你应该这样做。
文档明确指出您在运行时使用pthread_mutex_init
而另一个宏用于静态分配的互斥锁,我认为没有任何理由不这样做。
答案 3 :(得分:1)
您的GetFastNativeMutex
绝不是工厂职能。它总是返回相同互斥锁的副本,工厂的要点是抽象分配和创建新对象,而不是一直重用同一个。所以不,这对于使用相同的互斥锁作为全局变量无法完成的任何用法都是无效的。
来自here的引用:
引用副本的结果 互斥呼叫 pthread_mutex_lock()的, pthread_mutex_trylock() pthread_mutex_unlock(),和 pthread_mutex_destroy()未定义
答案 4 :(得分:-1)
如果所有myMutex实例共享相同的POSIX互斥锁,它“有效”。您当前有一个互斥锁,而不是每个MyClass对象一个。这肯定不是你想要的,不是吗?