2011-04-19 73 views
2

直到最近,我认为是错误检查互斥锁大多为与正确的代码没有什么价值一个调试工具,但后来我意识到它们具有可替代递归互斥体的属性,如:递归或错误检查互斥?

void foo() 
{ 
    int ok_to_unlock = !pthread_mutex_lock(m); 
    /* do something */ 
    if (ok_to_unlock) pthread_mutex_unlock(m); 
} 

注意pthread_mutex_lock如果调用者已经保持锁定,则成功时返回0,并返回EDEADLK。这种用法的优点是您不必担心超出任意递归锁定限制; “锁定计数”隐含在呼叫帧中。原则上这个习语也可能会稍微好一点,因为当调用线程已经持有锁时,从不会调用pthread_mutex_unlock

我的问题主要是关于然后风格:不使用错误检查互斥就像从代码的清晰度此减损?是否有其他原因,你不想这样使用它们?

+0

这听起来很主观。 :) – unwind 2011-04-19 13:23:45

+0

我想;但最后一句话中的问题有点非主观的转折点(非风格原因,这种用法会很糟糕)。 – 2011-04-19 13:26:25

+0

除了风格 - 我会研究PTHREAD_MUTEX_ERRORCHECK的性能。如果保存一些pthread_mutex_xxx调用,如果它检测到错误检查互斥是例如,它可能不值得。比普通或递归互斥锁慢10倍 – nos 2011-04-19 13:27:28

回答

2

这是主观的,但我觉得这使代码不太清楚。

+0

同意 - 未来的维护人员可能会正确地问为什么“错误”被锁在程序中返回,更不用说任何工具制定检查正确性可能不惜并发程序。 – 2011-04-19 13:33:11

1

我认为,无论性能提升你可能意识到会被首先使用错误检查互斥的成本所淹没。然而,即使这些成本可能很小,我也没有看到任何理由不使用这个习惯用法。我唯一的意见是使用变量名称,如locked而不是ok_to_unlock

+1

'locked'的问题是互斥锁*被锁定 - 这个变量指示谁有责任解锁它(我们或者主叫者)。不管你怎么称呼它,如果互斥体在我们出现之前没有被锁定,那么这个变量就是真的,如果它已经被锁定了,它就是假的。 – 2011-04-19 13:29:12

+2

我可以移动'!'的'if'和名称,如果'locked_by_caller' ... – 2011-04-19 13:36:40

2

注意pthread_mutex_lock回报0成功 和EDEADLK如果主叫方已持有锁。

你张贴的代码是不完全健壮,因为EDEADLK可能被返回的唯一可能的错误。如果互斥体没有正确初始化,还有EINVAL

在一个稍微切记,大卫Butenhof有一些interesting warnings关于使用递归互斥的。

+0

使用UB未初始化的互斥的结果,所以没有必要考虑这种情况。 – 2011-05-09 03:44:15

+0

+1链接。一段有趣的历史。我曾经同意这个观点,直到我明白stdio锁定和'flockfile'如何工作,这是一种递归互斥体。然后我意识到递归互斥允许您保护最小的数据操作单元,同时还允许调用者将更大的数据操作单元设置为原子 - 在stdio的情况下,确保多个文件IO操作作为原子单元进行。 – 2011-05-09 04:06:28