2022-09-07 C++并发编程(二十)

替换


前言

原子操作除了模板特化后的成员函数,还可以使用标准库中的普通函数。

这种函数前缀为 std::atomic_,包括std::atomic_load(),std::atomic_store(),std::atomic_exchange(),std::atomic_compare_exchange_weak(),std::atomic_compare_exchange_strong() 等。

以上是不可以设置内存次序参数的函数,如需设置内存次序,则需要在函数名后加后缀 _explicit。

另外,C++ 还允许 std::shared_ptr<> 对象作为非成员原子操作函数的参数,使得其支持基本的原子操作(载入,存储,交换,比较替换)。


一、原子操作的非成员函数

以下示例,展示了原子操作的非成员函数使用,和原子类成员函数区别不大,只是有两个版本,一个不可设置内存次序,一个可设内存次序。

可通过 debug 观察每一步的变化。

另外,虽然智能共享指针 std::shared_ptr<> 可以用于原子操作,但其不是无锁结构。

#include <atomic>
#include <iostream>
#include <memory>

struct atomicObj
{
    atomicObj() = default;

    atomicObj(int I, float F)
        : i(I)
        , f(F)
    {}

  private:
    int i = 0;
    float f = 0;
};

auto main() -> int
{
    std::atomic<atomicObj> obj;

    //原子操作函数的参数为原子类对象指针
    std::cout << std::atomic_is_lock_free(&obj) << std::endl;

    //无内存次序版本
    std::atomic_store(&obj, atomicObj{1, 1.0F});

    //有内存次序版本
    std::atomic_store_explicit(&obj, atomicObj{2, 2.0F},
                               std::memory_order_release);

    atomicObj test = std::atomic_load(&obj);

    test = std::atomic_load_explicit(&obj, std::memory_order_acquire);

    atomicObj test2 = std::atomic_exchange(&obj, atomicObj{3, 3.0F});

    test = std::atomic_exchange_explicit(&obj, atomicObj{4, 4.0F},
                                         std::memory_order_seq_cst);

    //比较替换的期望值 test 也是指针形式
    while (std::atomic_compare_exchange_weak(&obj, &test, atomicObj{5, 5.0F}))
    {
    }

    //比较替换的内存次序为两个,不可省略
    std::atomic_compare_exchange_weak_explicit(&obj, &test, atomicObj{6, 6.0F},
                                               std::memory_order_seq_cst,
                                               std::memory_order_relaxed);

    std::atomic_compare_exchange_strong(&obj, &test, atomicObj{6, 6.0F});

    std::atomic_compare_exchange_strong_explicit(
        &obj, &test, atomicObj{6, 6.0F}, std::memory_order_seq_cst,
        std::memory_order_relaxed);

    std::shared_ptr<atomicObj> sharedPtr = std::make_shared<atomicObj>(7, 7.0F);

    //智能共享指针 shared_ptr<> 的指针也可以作为原子操作函数的参数
    //但其并非无锁结构
    std::cout << std::atomic_is_lock_free(&sharedPtr) << std::endl;

    std::shared_ptr<atomicObj> local = std::atomic_load(&sharedPtr);

    local = std::atomic_load_explicit(&sharedPtr, std::memory_order_seq_cst);

    local =
        std::atomic_exchange(&sharedPtr, std::make_shared<atomicObj>(8, 8.0));

    local = std::atomic_exchange_explicit(&sharedPtr,
                                          std::make_shared<atomicObj>(8, 8.0),
                                          std::memory_order_seq_cst);

    std::atomic_store(&sharedPtr, local);

    std::atomic_store_explicit(&sharedPtr, local, std::memory_order_seq_cst);

    while (std::atomic_compare_exchange_weak(
        &sharedPtr, &local, std::make_shared<atomicObj>(9, 9.0F)))
    {
    }

    while (std::atomic_compare_exchange_weak_explicit(
        &sharedPtr, &local, std::make_shared<atomicObj>(9, 9.0F),
        std::memory_order_seq_cst, std::memory_order_relaxed))
    {
    }

    std::atomic_compare_exchange_strong(&sharedPtr, &local,
                                        std::make_shared<atomicObj>(10, 10.0F));

    std::atomic_compare_exchange_strong_explicit(
        &sharedPtr, &local, std::make_shared<atomicObj>(10, 10.0F),
        std::memory_order_seq_cst, std::memory_order_relaxed);

    return 0;
}

总结

虽然标准库准备了非成员函数的原子操作函数,但我想,如果是特化的原子类,还是用成员函数比较方便,且不容易出错,这种非成员函数,可能更主要的应用是智能共享指针的原子操作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不停感叹的老林_<C 语言编程核心突破>

不打赏的人, 看完也学不会.

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值