2012-06-23 82 views
14

按本article为什么要锁定一个std :: mutex两次'未定义的行为'?

如果你试图在同一个线程锁定一个非递归互斥两次之间没有解锁,你得到了一个未定义的行为。

我非常天真的头脑告诉我为什么他们不只是返回一个错误?这是UB的理由吗?

+0

您可能想要使用具有默认内存顺序的atomic_flag。它没有数据竞争,并且永远不会抛出异常,例如互斥锁可以处理多个解锁调用(并且可以放心地放弃,我可能会添加......)。或者,有原子(例如原子[bool]或原子[int](带有三角括号,而不是[])),它具有很好的功能,如load和compare_exchange_strong。 http://www.cplusplus.com/reference/atomic/atomic_flag/ http://www.cplusplus.com/reference/atomic/atomic/ – Andrew

+0

此外,由于'互斥体'可能与OS本地互斥体一起实现,那么它没有定义在不同的操作系统上可能会有什么不同,因此'std :: mutex'可能是操作系统提供的互斥体的一个小包装。 – Phil1970

回答

26

因为它从来没有发生在一个正确的程序中,并且检查从未发生过的事情是浪费的(并且为了检查它需要存储拥有的线程ID,这也是浪费的)。

请注意,它是未定义的,允许调试实现抛出一个异常,例如,同时仍然允许发布实现尽可能高效。

+1

好A,但是tbh我认为好的dbg实现应该断言,因为有时候ppl:P编写能够在不会产生太多噪音的情况下消除异常的代码。 :d – NoSenseEtAl

15

未定义的行为允许执行任何最快/最方便的操作。例如,一个非递归互斥锁的有效实现可能是一个单一位,其中锁定操作是通过循环中的原子比较和交换指令实现的。如果拥有互斥锁的线程试图再次锁定它,它将会因为它正在等待互斥锁解锁而死锁,但由于没有其他人可以解锁它(除非有一些其他线程不拥有它可以解锁它)线程将永远等待。