• 2022-08-29 C++并发编程(十六)



    老林的C语言新课, 想快速入门点此 <C 语言编程核心突破>


    C++并发编程(十六)


    前言

    上文讲述了最简单的原子标识,本文讲讲 std::atomic 原子布尔类。相比较 std::atomic_flag ,原子布尔类有更多的操作。


    一、操作 std::atomic 对象

    原子布尔类不可拷贝构造,不可拷贝赋值,可通过普通布尔类初始化,可接受普通布尔类赋值(不返回引用),可根据 is_lock_free() 函数判断是否为无锁结构:

        //初始化
        std::atomic<bool> atomicBool(true);
    
        //是否是无锁结构
        std::cout << atomicBool.is_lock_free() << std::endl;
    
        //原子变量赋值,但只返回值(false)不返回原子变量的引用
        //这个与普通的赋值语义是完全不同的。
        atomicBool = false;
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    std::atomic 可以调用 store() 函数进行写操作,用 load() 函数进行读操作,用 exchange() 函数进行读改写操作,返回原有值,并更新,同时可指定内存顺序.

        //读取原子变量
        bool normalBool = atomicBool.load(std::memory_order_acquire);
    
        //存储原子变量值
        atomicBool.store(true);
    
        //更新值(false),并返回原值(true)
        normalBool = atomicBool.exchange(false, std::memory_order_acq_rel);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    std::atomic 可以调用 compare_exchange_weak() 及 compare_exchange_strong() 函数实现比较替换操作。

    与直接获取原值并更新值的 exchange() 不同,比较替换函数 compare_exchange_weak() 及 compare_exchange_strong() 多了一个与原值比较的期望值参数 expected,是引用形式:

    public: bool compare_exchange_weak(
        bool &expected, bool __d, std::memory_order __m = memory_order_seq_cst) noexcept
    
    public: bool compare_exchange_strong(
        bool &expected, bool __d, std::memory_order __m = memory_order_seq_cst) noexcept
    
    • 1
    • 2
    • 3
    • 4
    • 5

    当原值与期望值 expected 值一致,则返回true,并更新新值。否则将原值赋予期望值 expected,并返回 false。

    weak 版本有一定概率即使原值与期望值 expected 相同,也不会更新既定值,只返回false,即虚假失败(spurious failure),所以通常放在 while 循环中,并且通常效率要高于 strong 版本。

    并且比较替换操作还有两个内存顺序参数。

    具体细节请看注释:

    #include 
    #include 
    
    auto main() -> int
    {
        //初始化
        std::atomic<bool> atomicBool(true);
    
        //是否是无锁结构
        std::cout << atomicBool.is_lock_free() << std::endl;
    
        //原子变量赋值,但只返回值(false)不返回原子变量的引用
        //这个与普通的赋值语义是完全不同的。
        atomicBool = false;
    
        //读取原子变量
        bool normalBool = atomicBool.load(std::memory_order_acquire);
    
        //存储原子变量值
        atomicBool.store(true);
    
        //更新值(false),并返回原值(true)
        normalBool = atomicBool.exchange(false, std::memory_order_acq_rel);
    
        bool expected = false;
    
        //与期待值 expected 比较,如果相同,更新既定值(true),返回true。
        // weak 版本有一定概率即使与 expected  相同,
        //也可能不会更新既定值,即虚假失败(spurious failure)
        //如果与 expected 不同,用原子变量值更新期待值expected,返回false
        //为了剔除虚假失败,我们一般要联合while循环,但语义也就变了,
        //语义变为与期待值比较,相同则更新既定值,不同则将原值赋值给期待值,更新既定值
        while (!atomicBool.compare_exchange_weak(expected, true) && !expected)
        {
        }
    
        // strong 版本不会产生虚假失败,其余和 weak 版本相同
        //一般 weak 版本更具效率,因为strong版本有内循环
        //但如果需要语义是与期待值(expected)相同则更改为既定值(false)同时返回true
        //否则与期待值不同,只更改期待值,并返回false,则需要用strong版本。
        //另外,此操作可以设定两个内存次序,因为有成功或失败两种状态
        //成功需读改写次序,失败只能是读次序
        //若不设定内存顺序,则为完全顺序,性能最低。
        bool result = atomicBool.compare_exchange_strong(
            expected, false, std::memory_order_acq_rel, std::memory_order_acquire);
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    总结

    原子布尔类操作大都比较简单,只是比较替换操作较难理解,需要多学多练。


    老林的C语言新课, 想快速入门点此 <C 语言编程核心突破>


  • 相关阅读:
    ELK高级搜索,深度详解ElasticStack技术栈-上篇
    python+opencv+深度学习实现二维码识别 计算机竞赛
    自然语言开发AI应用,利用云雀大模型打造自己的专属AI机器人
    XSS高级 svg 复现一个循环问题以及两个循环问题
    LeetCode简单题之合并相似的物品
    TypeScript常见面试题第十一节
    【蓝桥杯选拔赛真题30】python计算倒数和 青少年组蓝桥杯python 选拔赛STEMA比赛真题解析
    Python中的元素相乘与矩阵相乘(附Demo)
    QTableWidget中cell 和 item区别
    第八章、python中的序列、迭代器、生成器及可迭代对象------迭代器(iterator)与生成器(generator)
  • 原文地址:https://blog.csdn.net/m0_54206076/article/details/126586326