使用pthreads必须在获取锁之前在任何互斥锁上调用pthread_mutex_init()。
根据POSIX,锁定未初始化的互斥锁仅定义为具有优先级保护的互斥锁(opengroup : pthread_mutex_lock)
根据联机帮助页pthread_mutex_lock.3thr,如果在未经初始化的互斥锁上调用,它应返回EINVAL。 假设可移植性不是问题,编写如下代码是否有效(一个好主意?):
pthread_mutex_t lock;
int ret = pthread_mutex_lock(&lock);
if (ret != 0){
if(ret == EINVAL){
pthread_mutex_init(&lock, NULL);
} else {
/* other error */
}
}
还有另一种检查pthread_mutex是否已初始化的方法吗?
整个场景是图书馆的一部分(不幸的是政治不是C ++),我想避免最大限度的错误使用。即客户端可以初始化两次创建的对象,可以在正确初始化之前将对象传递给其他函数等。
目前在对象中有一个aditional标志,表示互斥锁是否已经初始化,我很想知道这是否真的有必要。
查看静态互斥量初始化的宏PTHREAD_MUTEX_INITIALIZER
的扩展,它只是扩展为一个所有成员都设置为0的结构。
我可以假设,如果不再需要,则不需要调用mutex_destroy,因为ressource本身已被释放(确定没有其他人使用它)?
更新: Jens的回答绝对正确。以下程序产生完全未定义的行为:
int main(int argc, char** argv)
{
pthread_mutex_t lock;
int ret = pthread_mutex_lock(&lock);
if (ret != 0) {
printf(" ERR : %d %s \n", ret, strerror(ret));
if (ret == EINVAL) {
pthread_mutex_init(&lock, NULL);
}
} else {
printf(" ok \n");
}
pthread_mutex_unlock(&lock);
return 0;
}
有时会出现僵局,有时会打印出来。 .....
答案 0 :(得分:4)
不,你无法察觉。可以为未初始化的互斥锁返回EINVAL
,但不一定非。
另外POSIX声明:
尝试初始化已初始化的互斥锁导致 未定义的行为。
所以你不应该试试。
最好的方法是完全避免这种情况并正确初始化变量。这应该通过宏PTHREAD_MUTEX_INITIALIZER
完成。
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
答案 1 :(得分:0)
至少要回答问题的这一部分,
<块引用>查看用于静态互斥初始化的宏 PTHREAD_MUTEX_INITIALIZER 的扩展,它只是扩展为一个所有成员都设置为 0 的结构。如果不再需要,我可以假设不需要调用 mutex_destroy,因为资源本身是释放了(确定没有其他人使用它)?
来自 man page 的 pthread_mutex_init
<块引用>PTHREAD_MUTEX_INITIALIZER 可用于初始化静态分配的互斥锁。除了不执行错误检查外,效果应等同于通过调用 pthread_mutex_init() 并将参数 attr 指定为 NULL 进行动态初始化。
来自 man page for win32 pthread_mutex_init
<块引用>在 Pthreads-w32 实现中,应用程序仍应在某个时刻调用 pthread_mutex_destroy,以确保释放互斥锁消耗的任何资源。
基于手册页声明静态初始化和动态初始化是等效的这一事实,这使我相信静态初始化的互斥锁在不再使用时应该总是被销毁。在 pthreads 手册页的 win32 版本中明确说明了这一点。此外,销毁使用 PTHREAD_MUTEX_INITIALIZER 分配的互斥锁不会返回错误,它会很高兴地返回 0,因此这样做没有害处。充其量它会释放不再需要的任何资源,并可能毒害互斥锁的值以将其标记为销毁,或者最坏的情况是什么都不做。
总而言之,为了可移植性,我总是会销毁任何已初始化的互斥锁,即使它是使用静态初始化程序完成的。