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

从C++标准视角:后申请自旋锁的线程先获锁且时间戳更晚是否合法?

问题分析:C++自旋锁场景下的输出合法性

首先看给出的C++自旋锁代码:

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

struct SpinLock{
   std::atomic<bool>  state;
   void lock(){
      bool expected = false;
      while(!state.compare_exchange_strong(expected,true,std::memory_order::acquire,std::memory_order::relaxed)){
        expected = false;
      }
   }
   void unlock(){
      state.store(false,std::memory_order::release);
   }
};
int main(){
    auto spin_lock = SpinLock{false};
    int i = 0;
    std::thread t1([&](){
        std::this_thread::sleep_for(std::chrono::seconds(1));
        spin_lock.lock();
        auto time_stamp = std::time(nullptr);
        std::cout<<"t1 " <<time_stamp <<"   "<< i<<"\n"; // #1
        spin_lock.unlock();
    });
    std::thread t2([&](){
        spin_lock.lock();
        i = 1;
        auto time_stamp = std::time(nullptr);
        std::cout<<"t2 " <<time_stamp<<"   "<< i<<"\n"; // #2
        spin_lock.unlock();
    });
    t1.join();
    t2.join();
}

用户提出的疑问是:是否存在符合C++标准的情况,使得输出为:

t1 1729172229 0
t2 1729172228 1


结论:该输出完全符合C++标准

原因如下:

  • C++内存模型不绑定真实物理时间:标准只定义了操作间的同步关系、修改顺序,不要求代码的执行顺序和物理时间严格对应。
  • 锁的获取顺序与时间戳读取顺序无关:
    当#1读取到i=0时,说明t1的CAS操作(lock中的compare_exchange_strong)在原子变量state的修改顺序中早于t2的CAS——也就是t1先抢占到了锁。此时t2还在自旋等待锁,它对i=1的写入还没执行,所以t1读取到i的初始值0是合理的。
    但t2的std::time(nullptr)调用完全可以在t1睡眠的1秒内就执行:t2启动后立刻进入lock循环,在自旋等待锁的过程中,可能早于t1醒来的时间就执行了时间戳读取(只是因为没拿到锁,后续的打印操作被延迟到t1解锁后才完成)。这就导致t2的时间戳数值更小(更早),但打印顺序在t1之后。
  • 同步关系的约束范围:自旋锁的acquire/release语义只约束锁保护的临界区内的操作(比如t1的i读取、t2的i写入),但std::time的调用不在临界区的依赖链中,不受锁的同步关系约束,因此它的执行时间可以和锁的获取顺序脱节。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 04:25:55