Joh*_*0te 9 c++ multithreading deadlock pthreads
假设我有两个变量,protected_var1并且protected_var2.让我们进一步假设这些变量是通过多个线程更新的,并且相当独立,通常是一个或另一个但不是两个都被处理 - 因此它们都有自己的互斥保护以提高效率.
假设:
- 我总是在需要两个锁的区域中按顺序锁定互斥锁(mutex1然后是mutex2).
-both互斥体被其他许多地方使用(比如只需要锁定mutex1,或者只是锁定mutex2).
在这种情况下,使用两者在函数结尾处解锁互斥锁的顺序是否有所不同?
void foo()
{
pthread_mutex_lock(&mutex1);
pthread_mutex_lock(&mutex2);
int x = protected_var1 + protected_var2;
pthread_mutex_unlock(&mutex1); //Does the order of the next two lines matter?
pthread_mutex_unlock(&mutex2);
}
Run Code Online (Sandbox Code Playgroud)
很久以前我在一次关于这种情况的采访中被问到一个问题,我觉得答案是肯定的 - 这两个解锁的顺序很重要.我不能为我的生活弄清楚如何在这两者被使用的情况下以相同的顺序获得锁定时如何导致死锁.
Jam*_*nze 12
只要您不尝试在版本之间获取另一个锁定,顺序就无关紧要了.重要的是始终以相同的顺序获取锁; 否则,你冒着陷入僵局的风险.
编辑:
要扩展约束:您必须在互斥锁之间建立严格的排序,例如mutex1在前面mutex2(但此规则对任意数量的互斥锁都有效).如果您没有按顺序在其后面输入互斥锁,则您只能请求锁定互斥锁; 例如,mutex1如果您持有锁,您可能不会要求锁定mutex2.任何时候这些规则都得到尊重,你应该是安全的.关于发布,如果你发布mutex1,然后尝试在发布之前重新获取它mutex2,你违反了规则.在这方面,在类似堆栈的顺序方面可能存在一些优点:最后获得的总是第一次释放.但这是一种间接影响:规则是mutex1如果你持有一个
锁定就不能请求锁定mutex2.无论您是否在获得锁定mutex1时锁定了锁定mutex2.
我不能为我的生活弄清楚如何在这两者被使用的情况下以相同的顺序获得锁定时如何导致死锁.
在这种情况下,我不认为解锁互斥锁的顺序可能是导致死锁的原因.
由于pthread_mutex_unlock()不阻塞,无论两个调用的顺序如何,两个互斥锁总是会被解锁.
请注意,如果您尝试获取两次解锁呼叫之间的任何锁定,则可以完全更改图片.
这与锁定的正确性无关。原因是,即使假设其他线程正在等待锁定 mutex1 和 mutex2,最坏的情况是一旦您释放 mutex1(并获取 mutex1),它就会立即被调度。然后它会阻塞等待 mutex2,您所询问的线程将在它再次被调度后立即释放,并且没有理由不应该很快发生(立即,如果这些是唯一在玩的两个线程)。
因此,与您首先发布 mutex2 并且因此只有一个重新调度操作相比,在这种确切情况下可能会降低性能成本。但是,您通常不会期望预测或担心什么,这一切都在“调度通常不是确定性的”的范围内。
但是,您释放锁的顺序肯定会影响一般的调度。假设有两个线程在等待您的线程,其中一个在 mutex1 上被阻塞,而另一个在 mutex2 上被阻塞。结果可能是,无论您先释放哪个锁,该线程都会先运行,这仅仅是因为您的线程已经过时(消耗的时间超过整个时间片),因此一旦其他任何东西可运行,就会被取消调度。但这不会在其他正确的程序中导致错误:不允许您依赖在您的线程一旦释放第一个锁就被取消调度。因此,如果您有多个内核,这两个等待线程的运行顺序(如果您有多个内核同时运行)或两个在一个内核上交替运行,那么无论您释放锁的顺序如何,都必须同样安全。
| 归档时间: |
|
| 查看次数: |
5534 次 |
| 最近记录: |