C++ 原子操作为什么使用 .load() 和 .store()

3 篇文章 0 订阅


在 C++ 中,当使用 std::atomic 类型时,load() 和 store() 方法是为了确保对变量的访问和修改是线程安全的。
虽然 std::atomic 支持使用等号操作符(=)来进行赋值和读取,但是理解为什么使用 load() 和 store() 比直接使用 = 更好,尤其是从概念上理解这些操作的原子性,是很重要的。

原子操作的概念

在多线程环境中,原子操作意味着一个操作是不可分割的:要么完全执行,要么不执行,且在其执行过程中不会被其他线程的操作中断。std::atomic 提供了对基础类型(如 int、bool,以及自定义枚举等)进行原子操作的机制。

明确的线程安全语义:

使用 load() 和 store() 明确地表达了这是一个原子操作。它向代码的读者传达了当前正在使用原子操作进行读取和写入操作,这对理解和维护代码的开发者来说非常重要。

避免歧义:

  • 使用 = 进行赋值或读取虽然对 std::atomic 是有效的,但是在代码审查或阅读时,这样的代码可能会被误解为普通的非原子操作。例如:
    enum RunState
    {
    	Ready,  // 就绪
    	Pause,  // 暂停
    	Runing, // 运行中
    };
    
    std::atomic<RunState> runState;
    
    runState = Ready;  // 可能被误认为是普通的赋值操作
    
    使用 store() 和 load() 可以清晰地表明:
    runState.store(Ready);  // 显式地表明这是一个原子存储操作
    

跨平台一致性

在不同的平台或编译器实现中,std::atomic 的原子性操作实现可能有所不同。通过使用标准的 .load() 和 .store(),可以确保代码在不同平台上的行为一致且正确。

特定的内存序语义

std::atomic 提供了多种内存序选项,如 memory_order_relaxed、memory_order_acquire 和 memory_order_release,这些可以通过 .load() 和 .store() 方法的参数来指定,从而影响操作的内存序。对于 = 操作符,虽然默认情况下也使用内存序,但它通常不能直接指定这些选项。例如:

runState.store(Ready, std::memory_order_release);

总结

使用 load() 和 store() 而不是 = 的原因主要在于它们能清楚地表达出原子操作的意图,使代码在多线程环境下更安全、更可读,并提供了跨平台一致性和更丰富的内存序选项。如果代码涉及到多线程,并希望确保线程安全性,那么尽量使用 .load() 和 .store(),即使 = 操作符在很多情况下也能工作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值