5.2.1 标准原子类型

标准原子类型(atomic types)可以在头文件中找到。所有在这种类型上的操作都是原子的,虽然可以使用互斥量去达到原子操作的效果,但只有在这些类型上的操作是原子的(语言明确定义)。实际上,标准原子类型都很相似:它们(大多数)都有一个is_lock_free()成员函数,这个函数允许用户决定是否直接对一个给定类型使用原子指令(x.is_lock_free()返回true),或对编译器和运行库使用内部锁(x.is_lock_free()返回false)。

只用std::atomic_flag类型不提供is_lock_free()成员函数。这个类型是一个简单的布尔标 志,并且在这种类型上的操作都需要是无锁的(lock-free);当你有一个简单无锁的布尔标志 是,你可以使用其实现一个简单的锁,并且实现其他基础的原子类型。当你觉得“真的很简 单”时,就说明:在 std::atomic_flag 对象明确初始化后,做查询和设置(使用test_and_set() 成员函数),或清除(使用clear()成员函数)都很容易。这就是:无赋值,无拷贝,没有测试和清 除,没有其他任何操作。

剩下的原子类型都可以通过特化std::atomic<>类型模板而访问到,并且拥有更多的功能,但可能不都是无锁的(如之前解释的那样)。在最流行的平台上,期望原子变量都是无锁的内置类型(例如 std::atomic<int>std::atomic<void*>),但这没有必要。你在后面将会看到,每个特化接口所反映出的类型特点;位操作(如&=)就没有为普通指针所定义,所以它也就不能为原 子指针所定义。

除了直接使用std::atomic<>类型模板外,你可以使用在表5.1中所示的原子类型集。由于历 史原因,原子类型已经添加入C++标准中,这些备选类型名可能参考相应的std::atomic<>特 化类型,或是特化的基类。在同一程序中混合使用备选名与std::atomic<>特化类名,会使代码的移植大打折扣。

表5.1 标准原子类型的备选名和与其相关的  std::atomic<> 特化类

原子类型

相关特化类

atomic_bool

std::atomic<bool>

atomic_char

std::atomic<char>

atomic_schar

std::atomic<signed char>

atomic_uchar

std::atomic<unsigned char>

atomic_int

std::atomic<int>

atomic_uint

std::atomic<unsigned>

atomic_short

std::atomic<short>

atomic_ushort

std::atomic<unsigned short>

atomic_long

std::atomic<long>

atomic_ulong

std::atomic<unsigned long>

atomic_llong

std::atomic<long long>

atomic_ullong

std::atomic<unsigned long long>

atomic_char16_t

std::atomic<char16_t>

atomic_char32_t

std::atomic<char32_t>

atomic_wchar_t

std::atomic<wchar_t>

C++标准库不仅提供基本原子类型,还定义了与原子类型对应的非原子类型,就如同标准库中的  std::size_t 。如表5.2所示这些类型:

表5.2 标准原子类型定义(typedefs)和对应的内置类型定义(typedefs)

原子类型定义

标准库中相关类型定义

atomic_int_least8_t

int_least8_t

atomic_uint_least8_t

uint_least8_t

atomic_int_least16_t

int_least16_t

atomic_uint_least16_t

uint_least16_t

atomic_int_least32_t

int_least32_t

atomic_uint_least32_t

uint_least32_t

atomic_int_least64_t

int_least64_t

atomic_uint_least64_t

uint_least64_t

atomic_int_fast8_t

int_fast8_t

atomic_uint_fast8_t

uint_fast8_t

atomic_int_fast16_t

int_fast16_t

atomic_uint_fast16_t

uint_fast16_t

atomic_int_fast32_t

int_fast32_t

atomic_uint_fast32_t

uint_fast32_t

atomic_int_fast64_t

int_fast64_t

好多种类型!不过,它们有一个相当简单的模式;对于标准类型进行typedef T,相关的原子类型就在原来的类型名前加上atomic_的前缀:atomic_T。除了singed类型的缩写是s, unsigned的缩写是u,和long long的缩写是llong之外,这种方式也同样适用于内置类型。对 于  std::atomic<T> 模板,使用对应的T类型去特化模板的方式,要好于使用别名的方式。

通常,标准原子类型是不能拷贝和赋值,他们没有拷贝构造函数和拷贝赋值操作。但是,因为可以隐式转化成对应的内置类型,所以这些类型依旧支持赋值,可以使用load()store()成员函数,exchange()compare_exchange_weak()compare_exchange_strong()。它们都支持复合赋值符:+=, -=, *=, |= 等等。并且使用整型和指针的特化类型还支持 ++ 和 --。当 然,这些操作也有功能相同的成员函数所对应:fetch_add(), fetch_or() 等等。返回值通过赋值操作返回,并且成员函数不是对值进行存储(在有赋值符操作的情况下),就是对值进行操作(在命名函数中)。这就能避免赋值操作符返回引用。为了获取存储在引用的的值,代码需要执行单独的读操作,从而允许另一个线程在赋值和读取进行的同时修改这个值,这也就为条件竞争打开了大门。

std::atomic<> 类模板不仅仅是一套特化的类型,其作为一个原发模板也可以使用用户定义类型创建对应的原子变量。因为,它是一个通用类模板,很多成员函数的操作在这种情况下有所限制:load(), store()(赋值和转换为用户类型), exchange(), compare_exchange_weak()和 compare_exchange_strong()。

每种函数类型的操作都有一个可选内存排序参数,这个参数可以用来指定所需存储的顺序。 在5.3节中,会对存储顺序选项进行详述。现在,只需要知道操作分为三类:

1)Store操作,可选如下顺序:memory_order_relaxed, memory_order_release, memory_order_seq_cst。

2)Load操作,可选如下顺序:memory_order_relaxed, memory_order_consume,memory_order_acquire, memory_order_seq_cst。

3)Read-modify-write(读-改-写)操作,可选如下顺序:memory_order_relaxed, memory_order_consume, memory_order_acquire, memory_order_release, memory_order_acq_rel, memory_order_seq_cst。 所有操作的默认顺序都是memory_order_seq_cst。

现在,让我们来看一下每个标准原子类型进行的操作,就从  std::atomic_flag 开始吧。

5.2.1 标准原子类型相关推荐

  1. C++`中的原子操作和原子类型

    5.2 C++中的原子操作和原子类型 原子操作 是个不可分割的操作. 在系统的所有线程中,你是不可能观察到原子操作完成了一半这种情况的: 它要么就是做了,要么就是没做,只有这两种可能. 如果从对象读取 ...

  2. c++ 原子操作 赋值_5.2 C++中的原子操作和原子类型

    5.2 C++中的原子操作和原子类型 原子操作 是个不可分割的操作. 在系统的所有线程中,你是不可能观察到原子操作完成了一半这种情况的: 它要么就是做了,要么就是没做,只有这两种可能. 如果从对象读取 ...

  3. 第5章 C++内存模型和原子类型操作

    第5章 C++内存模型和原子类型操作 本章主要内容 ※ C++11内存模型详解 ※ 标准库提供的原子类型 使用各种原子类型 ※ 原子操作实现线程同步功能 C++11标准中,有一个十分重要特性,常被程序 ...

  4. C++11 原子类型与原子操作

    文章目录 1.认识原子操作 2.C++11 实现原子操作 3.内存模型:强顺序与弱顺序 参考文献 1.认识原子操作 原子操作是在多线程程序中"最小的且不可并行化的"操作,意味着多个 ...

  5. Rust原子类型和内存排序

    简介 原子类型在构建无锁数据结构,跨线程共享数据,线程间同步等多线程并发编程场景中起到至关重要的作用.本文将从Rust提供的原子类型和原子类型的内存排序问题两方面来介绍. Rust原子类型 Rust标 ...

  6. bitset类型, 标准库类型

    C++ primer 17.2 bitset类型, 标准库类型 1 使得位运算更容易实现, 并且能够处理超过最长整型大小的位集合. bitset定义在bitset中 定义和初始化bitset 1 bi ...

  7. 【SAP技术】SAP MM 如何看一个自定义移动类型是复制哪个标准移动类型而创建的?

    [SAP技术]SAP MM 如何看一个自定义移动类型是复制哪个标准移动类型而创建的? 比如项目上有一个自定义移动类型Z59,是复制551移动类型而定义的. OMJJ配置界面里,是有一个Ref字段.如下 ...

  8. 深入解析Java AtomicInteger 原子类型

    深入解析Java AtomicInteger原子类型 在进行并发编程的时候我们需要确保程序在被多个线程并发访问时可以得到正确的结果,也就是实现线程安全.线程安全的定义如下: 当多个线程访问某个类时,不 ...

  9. C++内存模型和原子类型操作

    C++内存模型和原子类型操作 std::memory_order初探 动态内存模型可以理解为存储一致性模型,主要是从行为上来看多个线程对同一个对象读写操作时所做的约束,动态内存理解起来会有少许复杂,涉 ...

最新文章

  1. https://www.zhihu.com/question/41564604
  2. TabBarItem图片不显示的原因
  3. 初识微信小程序第一弹
  4. 仿射变换 c语言,c语言数字图像处理(三):仿射变换
  5. 12 python语言语句块的标记是_7. 简单语句
  6. CodeIgniter学习笔记一:基本结构、控制器、视图、超级对象、数据库
  7. 【Python数据预处理】 归一化(按列减均值,除方差),标准化(按列缩放到指定范围),正则化(范数)
  8. 【Linux】一步一步学Linux——iptables命令(186)
  9. 通过修改注册表设定浏览器的却省值
  10. onpagefinished等了很久才执行_学了那么多精准引流推广的方法 你知道什么才是最重要的吗...
  11. “约见”面试官系列之常见面试题之第五十六篇之typeof返回的数据类型(建议收藏)
  12. win10 + VS2015 + EF6 + MySQL
  13. 获取音频频响和失真_专业音响设备_音频功放失真的四大要点及改善方法
  14. C# 类中的静态代码块
  15. JavaScript 中级篇:模块化编程
  16. 这些中国扶贫路上的“组合拳”,你见过吗?
  17. 释放数据融合价值!腾讯Angel PowerFL荣获2021数博会“领先科技成果奖”
  18. STM32F103ZE uIP DM9051 SPI以太网移植指南
  19. c#控件弹幕效果_仿B站弹幕,极简Android开源弹幕控件:EasyDanmaku
  20. VScode remote development 远程开发

热门文章

  1. python爬虫的用途_python爬虫用代理ip有什么用途?
  2. 眼坐标系和世界坐标系的相互转换
  3. TOP100summit:【分享实录-QQ空间】10亿级直播背后的技术优化
  4. 广发银行大数据管控互联网风险
  5. mysql cluster 乱码_Mysql中文乱码问题完美解决方案
  6. java中logger关闭log_Log4J如何关闭Logger对象的IO流资源
  7. Unity3D开发的赛车单机小游戏详细介绍(附有游戏下载链接)
  8. 网站 测试服务器配置,安装调试、软件测试、网站测试 配置维护环境配置、安全维护、安全运维等与服务器相关业务...
  9. 开发打开设置洁面_用了两到三年的华为手机,一键打开quot;开发者选项quot;,帮助性能加速...
  10. 2022-03-23 转载C++中std::auto_ptr被废弃,由std::unique_ptr代替的原因