关注公众号获取更多信息:

C++11提供了一个原子类型std::atomic<T>,可以使用任意类型作为模板参数,C++11内置了整型的原子变量,可以方便的使用原子变量,使用原子变量就不用互斥变量来保护该变量了。

每个 std::atomic 模板的实例化和全特化定义一个原子类型。若一个线程写入原子对象,同时另一线程从它读取,则行为良好定义(数据竞争的细节我们会在下节--内存模型里讲解)

另外,对原子对象的访问可以建立线程间同步,并按 std::memory_order 所对非原子内存访问定序。

需要注意的是,std::atomic 既不可复制亦不可移动。

由于std::atomic 是一个模板,C++11中定义了该模板特化的一些要求:

主模板

主 std::atomic 模板可用任何满足可复制构造 (CopyConstructible) 及可复制赋值 (CopyAssignable) 的可平凡复制 (TriviallyCopyable)  类型 T 特化。若下列任何值为 false 则程序为谬构:

  • std::is_trivially_copyable<T>::value

  • std::is_copy_constructible<T>::value

  • std::is_move_constructible<T>::value

  • std::is_copy_assignable<T>::value

  • std::is_move_assignable<T>::value

std::atomic<bool> 使用初等模板。它保证是标准布局结构体。

偏特化

标准库为下列类型提供 std::atomic 模板的特化,它们拥有初等模板所不拥有的额外属性:

对所有指针类型的部分特化 std::atomic<U*> 。这些特化拥有标准布局、平凡默认构造函数 (C++20 前)和平凡析构函数。除了为所有原子类型提供的操作,这些特化额外支持适合指针类型的原子算术运算,例如 fetch_add 、 fetch_sub 。

对整数类型的特化

以下列整数类型之一实例化时, std::atomic 提供适合于整数类型的额外原子操作,例如 fetch_add 、 fetch_sub 、 fetch_and 、 fetch_or 、 fetch_xor :

  • 字符类型 char 、 char8_t  (C++20 起)、 char16_t 、 char32_t 和 wchar_t ;

  • 标准有符号整数类型:signed char 、 short 、 int 、 long 和 long long ;

  • 标准无符号整数类型:unsigned char 、 unsigned short 、 unsigned int 、 unsigned long 和 unsigned long long ;

  • 任何头文件 <cstdint> 中的 typedef 所需的额外整数类型。

另外,结果的 std::atomic<Integral> 特化拥有标准布局、平凡默认构造函数 (C++20 前)和平凡析构函数。定义有符号整数算术为使用补码;无未定义结果。

atomic 用法

这次我们就不一一介绍atomic的API了,我们从atomic的定义反观atomic的用法:

template < class T > struct atomic {    bool is_lock_free() const volatile;    bool is_lock_free() const;    void store(T, memory_order = memory_order_seq_cst) volatile;    void store(T, memory_order = memory_order_seq_cst);    T load(memory_order = memory_order_seq_cst) const volatile;    T load(memory_order = memory_order_seq_cst) const;    operator  T() const volatile;    operator  T() const;    T exchange(T, memory_order = memory_order_seq_cst) volatile;    T exchange(T, memory_order = memory_order_seq_cst);    bool compare_exchange_weak(T &, T, memory_order, memory_order) volatile;    bool compare_exchange_weak(T &, T, memory_order, memory_order);    bool compare_exchange_strong(T &, T, memory_order, memory_order) volatile;    bool compare_exchange_strong(T &, T, memory_order, memory_order);    bool compare_exchange_weak(T &, T, memory_order = memory_order_seq_cst) volatile;    bool compare_exchange_weak(T &, T, memory_order = memory_order_seq_cst);    bool compare_exchange_strong(T &, T, memory_order = memory_order_seq_cst) volatile;    bool compare_exchange_strong(T &, T, memory_order = memory_order_seq_cst);    atomic() = default;    constexpr atomic(T);    atomic(const atomic &) = delete;    atomic & operator=(const atomic &) = delete;    atomic & operator=(const atomic &) volatile = delete;    T operator=(T) volatile;    T operator=(T);};

可以看出,我们常用的API如下:

(构造函数)

构造原子对象
(公开成员函数)

operator=

存储值于原子对象
(公开成员函数)

is_lock_free

检查原子对象是否免锁
(公开成员函数)

store

原子地以非原子对象替换原子对象的值
(公开成员函数)

load

原子地获得原子对象的值
(公开成员函数)

operator T

从原子对象加载值
(公开成员函数)

exchange

原子地替换原子对象的值并获得它先前持有的值
(公开成员函数)

compare_exchange_weakcompare_exchange_strong

原子地比较原子对象与非原子参数的值,若相等则进行交换,若不相等则进行加载
(公开成员函数)

除了这些常用的API,我们常用的API还有一些特化的API(之前我们说过,只有整数类型和指针类型有特化,所以这些API只有整数类型和指针类型可用):

fetch_add

原子地将参数加到存储于原子对象的值,并返回先前保有的值
(公开成员函数)

fetch_sub

原子地从存储于原子对象的值减去参数,并获得先前保有的值
(公开成员函数)

fetch_and

原子地进行参数和原子对象的值的逐位与,并获得先前保有的值
(公开成员函数)

fetch_or

原子地进行参数和原子对象的值的逐位或,并获得先前保有的值  
(公开成员函数)

fetch_xor

原子地进行参数和原子对象的值的逐位异或,并获得先前保有的值  
(公开成员函数)

operator++operator++(int)operator--operator--(int)

令原子值增加或减少一
(公开成员函数)

operator+=operator-=operator&=operator|=operator^=

加、减,或与原子值进行逐位与、或、异或
(公开成员函数)

例子

下面我们用一个例子结束本文:

// constructing atomics#include <iostream>       // std::cout#include <atomic>         // std::atomic, std::atomic_flag, ATOMIC_FLAG_INIT#include <thread>         // std::thread, std::this_thread::yield#include <vector>         // std::vector
std::atomic<bool> ready (false);std::atomic_flag winner = ATOMIC_FLAG_INIT;
void count1m (int id) {  while (!ready) { std::this_thread::yield(); }      // wait for the ready signal  for (volatile int i=0; i<1000000; ++i) {}          // go!, count to 1 million  if (!winner.test_and_set()) { std::cout << "thread #" << id << " won!\n"; }};
int main (){  std::vector<std::thread> threads;  std::cout << "spawning 10 threads that count to 1 million...\n";  for (int i=1; i<=10; ++i) threads.push_back(std::thread(count1m,i));  ready = true;  for (auto& th : threads) th.join();
  return 0;}

可能的输出:

spawning 10 threads that count to 1 million...thread #7 won!

走进C++11(三十七)原子操作之 std::atomic相关推荐

  1. C++11 并发指南六(atomic 类型详解三 std::atomic (续))

    C++11 并发指南六( <atomic> 类型详解二 std::atomic ) 介绍了基本的原子类型 std::atomic 的用法,本节我会给大家介绍C++11 标准库中的 std: ...

  2. C++11 并发指南六( atomic 类型详解二 std::atomic )

    C++11 并发指南六(atomic 类型详解一 atomic_flag 介绍)  一文介绍了 C++11 中最简单的原子类型 std::atomic_flag,但是 std::atomic_flag ...

  3. c++ 11 原子操作库 (std::atomic)(一)

    定义于头文件 <atomic> atomic 类模板及其针对布尔.整型和指针类型的特化 template< class T >    struct atomic; (1) (C ...

  4. c++ 11 原子操作库 (std::atomic)(二)

    定义于头文件 <atomic> atomic 类模板及其针对布尔.整型和指针类型的特化 每个 std::atomic 模板的实例化和全特化定义一个原子类型.若一个线程写入原子对象,同时另一 ...

  5. unique函数_走进C++11(三十四)unique_ptr

    std::unique_ptr是C++11标准中用来取代std::auto_ptr的指针容器(在C++11中,auto_ptr被废弃).它不能与其它unique_ptr类型的指针对象共享所指对象的内存 ...

  6. c+++11并发编程语言,C++11并发编程:多线程std:thread

    原标题:C++11并发编程:多线程std:thread 一:概述 C++11引入了thread类,大大降低了多线程使用的复杂度,原先使用多线程只能用系统的API,无法解决跨平台问题,一套代码平台移植, ...

  7. 美学心得(第二百三十七集) 罗国正

    美学心得(第二百三十七集) 罗国正 (2022年5月)   3023.中国伟大的科学家钱学森先生的这些观点,非常值得大家思考.研究,他说:"现代科学技术要分成八个大部门,它们是自然科学.社会 ...

  8. 【正点原子Linux连载】第三十七章 Linux内核移植 -摘自【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.0

    1)实验平台:正点原子阿尔法Linux开发板 2)平台购买地址:https://item.taobao.com/item.htm?id=603672744434 2)全套实验源码+手册+视频下载地址: ...

  9. 第三十七章 Caché 命令大全 ZWRITE 命令

    文章目录 第三十七章 Caché 命令大全 ZWRITE命令 重点 大纲 参数 描述 `ZWRITE`不带参数 `ZWRITE`带参数 Variables Non-Display Characters ...

最新文章

  1. ssh服务、密钥登陆配置
  2. javacurrentmap_Java ConcurrentHashMap.forEach方法代码示例
  3. 深入浅出Java核心技术开篇(总结)
  4. LIO-SAM探秘第三章之代码解析(五) --- imuPreintegration.cpp
  5. Nginx_PHP缓存设置的整理对比
  6. MacbookAir2011用U盘重装10.13.6High Sierra系统
  7. 用计算机绘制颗粒级配曲线,EXcel如何绘制颗粒级配曲线图
  8. mysql geometry查询返回值_使用MySQL的geometry类型处理经纬度距离问题的方法
  9. List集合过滤不符合条件的数据
  10. node进程cpu 100%问题排查
  11. 51单片机和315M无线发射模块编码与解码
  12. 牛客小白月赛21 I I love you(dp的优化)
  13. 【微信支付】APP支付和APIJS支付
  14. 【Java接口】限制App登录次数
  15. 对JAVA多态的理解
  16. openVPN服务端搭建
  17. strcasecmp与stricmp
  18. 一个人下班后,如何高质量提升自己
  19. Dmaven.multiModuleProjectDirectory system property is not set
  20. 匹兹堡Mac高清动态壁纸

热门文章

  1. 赶鸭子上架的cdq分治
  2. 数仓建模—建模方法论之范式建模
  3. 在chrome网页上通过点击链接或执行js打开本地文件夹
  4. perl替换数组元素
  5. 【软考备战·希赛网每日一练】2023年4月14日
  6. 古筝教学视频——袁莎周望李萌林玲
  7. 开发中常见的架构模式
  8. 插装式两位两通电磁阀DSV-080-2NCP、DDSV-080-2NCP
  9. 电机控制-硬件系统设计
  10. kali linux 爆破工具实验