jas*_*ine 3 c++ multithreading mutex recursive-mutex
我在SO上读到这个答案:
因为递归互斥锁具有所有权感,所以抓取互斥锁的线程必须与释放互斥锁的线程相同.在非递归互斥锁的情况下,没有所有权感,任何线程通常都可以释放互斥锁,无论哪个线程最初使用互斥锁.
我对上一个陈述感到困惑.一个线程可以锁定一个互斥锁,另一个不同的线程可以解锁该互斥锁吗?我以为同一个线程应该是唯一能够解锁互斥锁的线程?或者是否有任何特定的互斥量允许这个?我希望有人能澄清一下.
大多数互斥锁是(或至少应该是)非递归的.互斥锁是一个可以原子获取或释放的对象,它允许保护多个线程之间共享的数据免受竞争条件,数据损坏和其他令人讨厌的事物的影响.
单个互斥锁只能由同一个调用链中的单个线程获取一次.在相同的线程上下文中尝试两次获取(或保持)相同的互斥锁应该被视为无效的场景,并且应该被适当地处理(通常通过ASSERT,因为您违反了代码的基本合同).
这应该被视为代码气味或黑客.递归互斥锁与标准互斥锁的不同之处在于,同一线程可以多次获取递归互斥锁.
需要递归互斥体的根本原因是缺乏所有权,并且类之间没有明确的目的或描述.例如,您的代码可能会调用另一个类,然后再调用您的类.然后,起始类可以尝试再次获取相同的互斥锁,并且因为您希望避免崩溃,所以将其实现为递归互斥锁.
这种颠倒的类层次结构可能导致各种令人头疼的问题,而递归互斥体只能为更基本的架构问题提供创可贴解决方案.
无论互斥锁的类型,应该始终是相同的,其获取和释放相同的互斥线程.您在代码中使用的一般模式是这样的:
Thread 1
Acquire mutex A
// Modify or read shared data
Release mutex A
Thread 2
Attempt to acquire mutex A
Block as thread 1 has mutex A
When thread 1 has released mutex A, acquire it
// Modify or read shared data
Release mutex A
Run Code Online (Sandbox Code Playgroud)
当您有多个可以同时获取的互斥锁时(例如,互斥锁A和B),它会变得更加复杂.您可能会遇到像这样的死锁情况:
Thread 1
Acquire mutex A
// Access some data...
*** Context switch to thread 2 ***
Thread 2
Acquire mutex B
// Access some data
*** Context switch to thread 1 ***
Attempt to acquire mutex B
Wait for thread 2 to release mutex B
*** Context switch to thread 2 ***
Attempt to acquire mutex A
Wait for thread 1 to release mutex A
*** DEADLOCK ***
Run Code Online (Sandbox Code Playgroud)
我们现在有一种情况,每个线程都在等待另一个线程释放另一个锁 - 这就是所谓的ABBA死锁模式.
为了防止这种情况,重要的是每个线程总是以相同的顺序获取互斥锁(例如,总是A,然后是B).
| 归档时间: |
|
| 查看次数: |
3426 次 |
| 最近记录: |