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

两个线程中compare_exchange_strong能否读取同一初始值并匹配成功?

关于C++ atomic compare_exchange_strong的线程同步问题

问题描述

在给定的自旋锁示例代码中,spin初始值为false,两个线程中的compare_exchange_strong操作是否都能读取该初始值false,并与预期值false匹配成功?个人认为标准的正式措辞并未禁止这种可能性,若该情况不可能,标准中何处有相关规定?

C++标准定义引用

根据C++标准[atomics.types.operations] p23中对compare_exchange_weak的定义:

bool compare_exchange_weak(T& expected, T desired, memory_order success, memory_order failure) noexcept;

Effects: Retrieves the value in expected.
It then atomically compares the value representation of the value pointed to by this for equality with that previously retrieved from expected, and if true, replaces the value pointed to by this with that in desired.
If and only if the comparison is true, memory is affected according to the value of success, and if the comparison is false, memory is affected according to the value of failure.
When only one memory_order argument is supplied, the value of success is order, and the value of failure is order except that a value of memory_order::acq_rel shall be replaced by the value memory_order::acquire and a value of memory_order::release shall be replaced by the value memory_order::relaxed.
If and only if the comparison is false then, after the atomic operation, the value in expected is replaced by the value pointed to by this during the atomic comparison. If the operation returns true, these operations are atomic read-modify-write operations ([intro.multithread]) on the memory pointed to by this. Otherwise, these operations are atomic load operations on that memory.

示例代码

#include <iostream>
#include <atomic>
#include <thread>
struct SpinLock{
    std::atomic<bool> atomic_;
    void lock(){
       bool expected = false;
       while (!atomic_.compare_exchange_strong(expected,true,std::memory_order_release,std::memory_order_relaxed)){

       }
    }
    void unlock(){
        atomic_.store(false, std::memory_order_release);
    }
};
int main(){
    SpinLock spin{false};
    auto t1 = std::thread([&](){
        spin.lock();
        spin.unlock();
    });
    auto t2 = std::thread([&](){
        spin.lock();
        spin.unlock();
    });
    t1.join();
    t2.join();
}

问题解答

这种情况不可能发生,核心原因在于compare_exchange_strong是原子的读-改-写操作(当返回true时),标准中明确规定这类操作具备原子性——即整个比较+替换的过程是不可分割的,不会被其他线程的原子操作打断。

具体来说,当其中一个线程(比如t1)执行compare_exchange_strong时,它会原子地完成以下步骤:

  • 读取atomic_的当前值(初始为false)
  • 和expected的值(false)比较,发现相等
  • 将atomic_的值替换为true

整个过程中,其他线程(t2)无法在步骤1和步骤3之间读取到atomic_的false值并完成自己的比较替换操作。因为原子读-改-写操作会独占访问目标内存位置,确保同一时间只有一个线程能成功完成这个完整的原子操作。

另外,标准中[intro.multithread]章节对原子操作的定义也明确了:原子操作的执行是不可中断的,多个线程对同一原子对象的原子操作会被串行化——也就是说,针对同一原子变量的所有原子操作,会按照某种全局可见的顺序依次执行,不会出现两个原子读-改-写操作同时“看到”初始值并都成功的情况。

你提到的compare_exchange_weak的标准定义里,也说明当操作返回true时属于原子读-改-写操作,而compare_exchange_strong和compare_exchange_weak的核心原子性语义是一致的,区别仅在于weak可能出现伪失败(即使值匹配也返回false),但strong不会有伪失败,且两者的成功路径都保证原子性。


内容的提问来源于stack exchange,提问作者xmh0511

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 14:36:06