为什么两次锁定std::mutex会导致“未定义行为”?

21
根据这篇文章
如果在同一线程中两次锁定非递归互斥量而在中间没有解锁,则会发生未定义行为。
我的非常幼稚的想法是为什么他们不只是返回一个错误呢?这必须是UB的原因吗?

你可能想要使用默认内存顺序的atomic_flag。它没有数据竞争,也不像mutex在多次解锁调用时抛出异常(而且我要补充的是,会无法控制地中止...)。或者,还有atomic(例如atomic [bool]或atomic [int](带有三角括号,而不是[])),它具有诸如load和compare_exchange_strong之类的好函数。http://www.cplusplus.com/reference/atomic/atomic_flag/ http://www.cplusplus.com/reference/atomic/atomic/ - Andrew
由于mutex可能是使用操作系统本地的mutex实现的,因此不定义在不同操作系统上可能会有什么不同,这样std::mutex就可以成为操作系统提供的mutex的薄包装器。 - Phil1970
2个回答

35
因为在正确的程序中这种情况永远不会发生,而对从未发生的事情进行检查是浪费的(并且进行此检查需要存储拥有线程ID,这也是浪费的)。请注意,它没有被定义允许调试实现抛出异常,例如,同时仍允许发布实现尽可能高效。

1
虽然A不错,但说实话我认为好的dbg实现应该使用assert,因为有时候人们会写吃掉异常而不发出任何声音的代码。 :D - NoSenseEtAl

16

未定义行为允许实现以最快/最方便的方式进行操作。例如,非递归互斥锁的高效实现可能是一个单一位,在其中锁定操作是通过循环中的原子比较和交换指令来实现的。如果拥有互斥锁的线程尝试再次锁定它,则会发生死锁,因为它正在等待互斥锁解锁,但由于除了某些线程错误地解锁外,没有其他人可以解锁它,所以该线程将永远等待。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接