You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否用std::atomic::wait替代互斥锁?是否存在死锁风险?

关于std::atomic::wait的死锁风险疑问

我在阅读StackOverflow的《C20 mutex with atomic wait》和《Can std::atomic be used sometimes instead of std::mutex in C?》两个问题后产生了疑问,想了解调用std::atomic::wait函数同步代码是否安全。不少资料显示可以使用该函数,但我认为其可能存在死锁风险,示例代码如下:

#include <atomic>
#include <iostream>
#include <thread>
#include <vector>

std::atomic<bool> lock = false;

void go(){
    bool expected = false;
    while(!lock.compare_exchange_strong(expected, true)) {
        lock.wait(true);
        expected = false;
    }

    std::cout << "Sincronizado" << std::endl;

    lock = false;

    lock.notify_all();
}

int main() {
    std::vector<std::thread> threads;
    threads.reserve(2);

    for(int i = 0; i < 2; i++)
        threads.emplace_back(go);

    for(auto& thread : threads)
        thread.join();
}

目前这段代码看似正常,但设想以下场景:

线程1:

  • 成功通过while(!lock.compare_exchange_strong(expected, true))竞争
  • 执行到lock = false;之前被抢占
  • 线程1被抢占

线程2:

  • while(!lock.compare_exchange_strong(expected, true))竞争失败
  • 开始执行lock.wait(true);
  • 在该函数内部(底层使用Futex)检查lock为true
  • 仍在该函数内,调用FUTEX_WAIT阻塞前被抢占

线程1:

  • 恢复执行,将lock设为false
  • 调用lock.notify_all();通知所有等待线程

线程2:

  • 恢复执行,开始执行FUTEX_WAIT阻塞
  • 是否会发生死锁?

请问该场景是否可能发生,还是我多虑了?


你多虑了,这个场景不会发生死锁。

原因在于std::atomic::wait的底层实现(比如Linux上的futex机制)在真正将线程阻塞前,会原子性地再次检查原子变量的值是否与预期值匹配。具体到你的场景:

当线程2恢复执行并准备进入阻塞时,FUTEX_WAIT操作会先原子性检查lock的当前值是否为true——此时lock已经被线程1设为false,不匹配预期值,因此wait会直接返回,不会阻塞线程2。

之后线程2会重置expected = false,再次执行compare_exchange_strong,此时lock是false,CAS操作会成功,线程2就能进入临界区执行后续代码。

另外需要注意:即使存在“虚假唤醒”(无通知情况下的唤醒),代码中的while循环也能保证逻辑正确性——这也是wait通常要配合循环使用的核心原因。

内容的提问来源于stack exchange,提问作者Lucas Paixão

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 21:30:24