如何理解 C++ Concurrency in Action 中相同 class 导致死锁问题的实例?
How to understand about instances of the same class cause deadlock issue in C++ Concurrency in Action?
我正在阅读 C++ Concurrency in Action,并遇到以下描述 deadlock
(第 47 ~ 48 页)的语句:
The common advice for avoiding deadlock is to always lock the two mutexes in the same order: if you always lock mutex A before mutex B, then you’ll never deadlock. Sometimes this is straightforward, because the mutexes are serving different purposes, but other times it’s not so simple, such as when the mutexes are each protecting a separate instance of the same class. Consider, for example, an operation that exchanges data between two instances of the same class; in order to ensure that the data is exchanged correctly, without being affected by concurrent modifications, the mutexes on both instances must be locked. However, if a fixed order is chosen (for example, the mutex for the instance supplied as the first parameter, then the mutex for the instance supplied as the second parameter), this can backfire: all it takes is for two threads to try to exchange data between the same two instances with the parameters swapped, and you have deadlock!
我对以下部分的含义很困惑:
However, if a fixed order is chosen (for example, the mutex for the instance supplied as the first parameter, then the mutex for the instance supplied as the second parameter), this can backfire: all it takes is for two threads to try to exchange data between the same two instances with the parameters swapped, and you have deadlock!
前面提到“an operation
”,后面提到“two threads to try to exchange data
”。作者想表达的真实场景是什么?
交换操作是可交换的,因此您无法保证算法会以相同的参数顺序执行此操作。因此,如果有对象 a
和 b
,一个线程可以执行 Swap(a, b)
,另一个线程可以执行 Swap(b, a)
,最终结果锁以不同的顺序默认。
如果时机不好,这将导致死锁。
请注意,这甚至可以强制三个对象和三个线程执行:Swap(a, b)
、Swap(b, c)
、Swap(c, a)
。这里锁定第一个参数而不是第二个参数也会导致死锁。
这里指的是这样的情况:
你有一个功能
void foo(bar& a, bar& b) {
lock_guard<mutex> lock1(a.mutex);
...
lock_guard<mutex> lock2(b.mutex);
}
乍一看,这似乎遵循了始终以相同顺序锁定互斥锁的建议。
但是如果你有
bar a, b;
foo
可以称为
foo(a, b);
在一个线程中,作为
foo(b, a);
在另一个。然后,你有一个僵局。
In previous, it refers "an operation", then it mentions "two threads to try to exchange data"
你错过了句子的结尾!它说 "two threads to try to exchange data between the same two instances"。它不是在谈论线程之间交换数据,它是在谈论一个线程在一个类型的两个实例之间交换数据,另一个线程在相同的两个实例之间交换数据。
我正在阅读 C++ Concurrency in Action,并遇到以下描述 deadlock
(第 47 ~ 48 页)的语句:
The common advice for avoiding deadlock is to always lock the two mutexes in the same order: if you always lock mutex A before mutex B, then you’ll never deadlock. Sometimes this is straightforward, because the mutexes are serving different purposes, but other times it’s not so simple, such as when the mutexes are each protecting a separate instance of the same class. Consider, for example, an operation that exchanges data between two instances of the same class; in order to ensure that the data is exchanged correctly, without being affected by concurrent modifications, the mutexes on both instances must be locked. However, if a fixed order is chosen (for example, the mutex for the instance supplied as the first parameter, then the mutex for the instance supplied as the second parameter), this can backfire: all it takes is for two threads to try to exchange data between the same two instances with the parameters swapped, and you have deadlock!
我对以下部分的含义很困惑:
However, if a fixed order is chosen (for example, the mutex for the instance supplied as the first parameter, then the mutex for the instance supplied as the second parameter), this can backfire: all it takes is for two threads to try to exchange data between the same two instances with the parameters swapped, and you have deadlock!
前面提到“an operation
”,后面提到“two threads to try to exchange data
”。作者想表达的真实场景是什么?
交换操作是可交换的,因此您无法保证算法会以相同的参数顺序执行此操作。因此,如果有对象 a
和 b
,一个线程可以执行 Swap(a, b)
,另一个线程可以执行 Swap(b, a)
,最终结果锁以不同的顺序默认。
如果时机不好,这将导致死锁。
请注意,这甚至可以强制三个对象和三个线程执行:Swap(a, b)
、Swap(b, c)
、Swap(c, a)
。这里锁定第一个参数而不是第二个参数也会导致死锁。
这里指的是这样的情况:
你有一个功能
void foo(bar& a, bar& b) {
lock_guard<mutex> lock1(a.mutex);
...
lock_guard<mutex> lock2(b.mutex);
}
乍一看,这似乎遵循了始终以相同顺序锁定互斥锁的建议。
但是如果你有
bar a, b;
foo
可以称为
foo(a, b);
在一个线程中,作为
foo(b, a);
在另一个。然后,你有一个僵局。
In previous, it refers "an operation", then it mentions "two threads to try to exchange data"
你错过了句子的结尾!它说 "two threads to try to exchange data between the same two instances"。它不是在谈论线程之间交换数据,它是在谈论一个线程在一个类型的两个实例之间交换数据,另一个线程在相同的两个实例之间交换数据。