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

未使用同步机制读取指向原子对象的指针是否安全?

未使用同步机制读取指向原子对象的指针是否安全?

嘿,这个问题问到点子上了,咱们好好掰扯清楚哈。

首先得敲个重点:直接读取那个普通指针g_atomic是完全不安全的——因为g_atomic本身只是个普通的指针变量,不是原子类型的!

你看,writer线程在循环里不停给g_atomic赋值新的指针地址,而reader线程毫无同步地去读它,这属于C++标准里明确禁止的数据竞争场景:一个线程写普通变量,另一个线程并发读,没有任何同步措施的话,读取结果完全没有保障——哪怕你确定它永远不会是nullptr也没用,数据竞争的核心问题不是值是否合法,而是普通变量的读写既没有原子性保证,也没有内存可见性的保障。

举个实际的例子:reader线程可能读到一个“半更新”的无效指针值(虽然多数硬件上指针赋值是原子的,但C++标准可不保证这点);或者writer线程早就更新了指针,但reader线程因为CPU缓存的原因,一直看不到最新的指针值,始终在读取旧的原子对象。

那你可能会疑惑,writer里加的std::atomic_thread_fence(std::memory_order_seq_cst)有用吗?抱歉,这个栅栏只对原子操作的内存顺序生效,而g_atomic是普通指针,栅栏没法给普通变量的读写带来任何同步效果。

要解决这个问题,有两个靠谱的方案:

  • 把g_atomic改成原子指针类型:std::atomic<std::atomic<int>*> g_atomic;,这样writer里的指针赋值、reader里的指针读取都是原子操作,再配合合适的内存顺序(比如seq_cst或者acquire/release),就能安全地实现线程间的同步。
  • 如果坚持用普通指针,那读写g_atomic的时候必须用互斥锁(比如std::mutex)来保护,确保同一时间只有一个线程访问这个指针,从根源上避免数据竞争。

另外还要提一句:就算你安全读到了指针,后续对原子对象的ptr->load()操作是安全的(因为对象本身是原子类型),但前提是指针的读取过程必须安全,不然拿到无效指针的话,后续操作根本无从谈起。

哦对了,writer线程不断new新的原子对象却不释放旧的,这会造成内存泄漏,但这是内存管理的问题,和线程安全无关哈。

最后再总结下:不管指向的是不是原子对象,普通指针的无同步并发读写肯定不安全,必须给指针的访问加上同步机制——要么用原子指针,要么用互斥锁。

备注:内容来源于stack exchange,提问作者Ahmed AEK

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.13 17:30:33