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

原子操作为何仍需锁?基于ResourcePool单例代码的技术疑问

单例模式代码分析

示例代码

class ResourcePool{
public:   
    ...
    static inline ResourcePool* singleton()
    {
        ResourcePool* p = _singleton.load(butil::memory_order_consume);
        if (p) {
            return p;
        }
        pthread_mutex_lock(&_singleton_mutex);
        p = _singleton.load(butil::memory_order_consume);
        if (!p) {
            p = new ResourcePool();
            _singleton.store(p, butil::memory_order_release);
        }
        pthread_mutex_unlock(&_singleton_mutex);
        return p;
    }
private:
    ....
    static butil::static_atomic<ResourcePool*> _singleton;
    static pthread_mutex_t _singleton_mutex;
};

说明:Butil::memory_order_consume是封装的boost memory_order_consume。

问题解答

问题一:在多核多线程环境中,首次执行butil::memory_order_consume加载操作,是否能确保指令顺序,防止其他线程在获取p指针前对其进行解引用?

memory_order_consume的核心是维护数据依赖关系的内存序:当线程通过该语义加载到非空的p指针后,所有依赖于p的指令(比如解引用p访问对象成员),绝对不会被编译器或CPU重排到加载p的操作之前。

结合代码里的store用了memory_order_release,两者能建立依赖同步:store之前的ResourcePool初始化操作,对通过consume加载到p的线程完全可见,且解引用p的操作必然是在拿到有效指针之后执行的,不会出现“提前解引用无效指针”的问题。

简单说:能确保依赖于p的解引用操作不会提前到加载p之前,避免无效指针访问的风险。

问题二:若ResourcePool实例已存在则直接返回,不存在则创建并执行_singleton.store(p, butil::memory_order_release),该操作本应通知其他线程,只需其他线程通过butil::memory_order_acquire加载即可,为何还要添加锁?若加锁是为了保证p=_singleton.load(butil::memory_order_consume)的唯一访问,那后续的store操作又有什么作用?

这是标准的**双重检查锁定(DCLP)**实现,锁和原子store的作用完全不同:

  1. 锁的核心作用:避免多线程同时创建实例
    如果没有锁,当多个线程同时检测到_singleton为空时,都会进入创建实例的分支,导致多个ResourcePool实例被构造,直接破坏单例的唯一性。锁的存在保证同一时间只有一个线程能进入“创建实例”的临界区,确保实例只会被初始化一次。

  2. store操作的作用:保证内存可见性和初始化顺序
    锁解决了实例唯一性问题,但线程之间的缓存一致性需要靠原子操作的内存序来保证:

    • 用release语义执行store,能确保new ResourcePool()的所有初始化代码,都在store完成前执行完毕;
    • 后续其他线程通过consume/acquire加载_singleton时,不仅能看到最新的指针值,还能看到指针指向的对象已经完成初始化的状态,不会出现“拿到指针但对象未初始化”的情况。

另外,第一次的load(consume)是快速路径优化:当实例已经存在时,线程不用加锁就能直接获取指针,避免了每次调用都加锁的性能损耗。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 06:13:26