CPU 忙等的死锁案例

一个死锁案例

代码部分逻辑:

1
2
3
4
5
6
7
for (int i = tid; i < work_size; i += thread_num) {
while (is_work_ready[i] == 0) {
// spin lock
}
// do work
foo(work[i]);
}

下面这段代码看起来是合理的,线程执行的状态依赖于 is_work_ready[i],通过这个变量实现主线程和子线程之间通信。但是实际上由于 CPU 会陷入忙等(busy-waiting),导致当主线程更新 flag 之后,子线程不会读取这个变量,陷入死锁。即「如果 is_work_ready 为 1,正常执行」,但是「is_work_ready 为 0 时,陷入死锁,无法恢复」。

有关多线程编程的方式:

  1. 如果代码涉及到主线程与子线程的通信,最好使用同步 API,不要使用简单的 dead loop 。比如 ChatGPT 建议使用 std::mutex + std::conditional_variable 通信。
  2. dead loop 内部增加 std::this_thread::sleep_for(std::chrono::milliseconds(1)); 可以避免死锁的出现
  3. 为什么把预处理放到线程内可以避免出现死锁?因为此时主线程与子线程没有发生通信,仅仅只有子线程拷贝主线程的内存,而且没有子线程的内存写入冲突,所以总体来看,是没有死锁的。(也没有使用基于 while 的 dead loop)

CPU 忙等的死锁案例
http://hebangwen.github.io/2025/02/26/deadloop/
作者
何榜文
发布于
2025年2月26日
许可协议