5.2.2 std::atomic_flag的相关操作
5.2.2 std::atomic_flag的相关操作
std::atomic_flag 是最简单的标准原子类型,它表示了一个布尔标志。这个类型的对象可以在两个状态间切换:设置和清除。它就是那么的简单,只作为一个构建块存在。我从未期待这个类型被使用,除非在十分特别的情况下。正因如此,它将作为讨论其他原子类型的起点,因为它会展示一些原子类型使用的通用策略。
std::atomic_flag 类型的对象必须被ATOMIC_FLAG_INIT初始化。初始化标志位是“清除”状态。这里没得选择;这个标志总是初始化为“清除”:
std::atomic_flag f = ATOMIC_FLAG_INIT;
这适用于任何对象的声明,并且可在任意范围内。它是唯一需要以如此特殊的方式初始化的原子类型,但它也是唯一保证无锁的类型。如果 std::atomic_flag 是静态存储的,那么就得保证其是静态初始化的,也就意味着没有初始化顺序问题;在首次使用时,其都需要初始化。
当你的标志对象已初始化,那么你只能做三件事情:销毁,清除或设置(查询之前的值)。这些事情对应的函数分别是:clear()成员函数,和test_and_set()成员函数。clear()和 test_and_set()成员函数可以指定好内存顺序。clear()是一个存储操作,所以不能有memory_order_acquire或memory_order_acq_rel语义,但是test_and_set()是一个“读-改- 写”操作,所有可以应用于任何内存顺序标签。每一个原子操作,默认的内存顺序都是 memory_order_seq_cst。例如:
f.clear(std::memory_order_release); // 1
bool x = f.test_and_set(); // 2
这里,调用clear()①明确要求,使用释放语义清除标志,当调用test_and_set()②使用默认内存顺序设置表示,并且检索旧值。
你不能拷贝构造另一个std::atomic_flag对象;你也不能将一个对象赋予另一个std::atomic_flag 对象。这并不是 std::atomic_flag 特有的,而是所有原子类型共有的。 一个原子类型的所有操作都是原子的,因赋值和拷贝调用了两个对象,这就就破坏了操作的原子性。在这样的情况下,拷贝构造和拷贝赋值都会将第一个对象的值进行读取,然后再写入另外一个。对于两个独立的对象,这里就有两个独立的操作了,合并这两个操作必定不是原子的。因此,操作就不被允许。
有限的特性集使得 std::atomic_flag 非常适合于作自旋互斥锁。初始化标志是“清除”,并且互斥量处于解锁状态。为了锁上互斥量,循环运行test_and_set()直到旧值为false,就意味着这个线程已经被设置为true了。解锁互斥量是一件很简单的事情,将标志清除即可。实现如下面的程序清单所示:
清单5.1 使用 std::atomic_flag 实现自旋互斥锁
class spinlock_mutex
{std::atomic_flag flag;public:spinlock_mutex() : flag(ATOMIC_FLAG_INIT){}void lock(){while(flag.test_and_set(std::memory_order_acquire));}void unlock(){flag.clear(std::memory_order_release);}
};
这样的互斥量是最最基本的,但是它已经足够 std::lock_guard<> 使用了(详见第3章)。其本质就是在lock()中等待,所以这里几乎不可能有竞争的存在,并且可以确保互斥。当我们看到内存顺序语义时,你将会看到它们是如何对一个互斥锁保证必要的强制顺序的。这个例子将在 5.3.6节中展示。
由于 std::atomic_flag 局限性太强,因为它没有非修改查询操作(注:c++20以后才新增test()函数,对atomic_flag状态无修改的只读访问函数),它甚至不能像普通的布尔标志那样使用。所以,你最好使用std::atomic<bool> ,接下来让我们看看应该如何使用它。
5.2.2 std::atomic_flag的相关操作相关推荐
- 5.2.3 std::atomic的相关操作
5.2.3 std::atomic的相关操作 最基本的原子整型类型就是 std::atomic<bool> .如你所料,它有着比 std::atomic_flag更加齐全的布尔标志特性.虽 ...
- 多项式相关操作学习笔记
多项式相关操作学习笔记 标签: 多项式 说在前边 记录一下相关的多项式操作,顺便存个模板.(多点求值之后的部分,有点写不动了...留坑留坑 多项式 定义 给定一个环\(R\)(\(R\)通常是交换环, ...
- 双向链表的创建和相关操作
http://blog.csdn.net/jw903/article/details/38947753 双向链表其实是单链表的改进. 当我们对单链表进行操作时,有时你要对某个结点的直接前驱进行操作时, ...
- (C++版)链表(一)——实现单向链表创建、插入、删除等相关操作
http://blog.csdn.net/fisherwan/article/details/25557545 前段时间用C语言实现了链表的相关操作,但是发现当时挺清楚的,过了一段时间又忘的差不多了, ...
- 5.2.5 标准的原子整型的相关操作
5.2.5 标准的原子整型的相关操作 如同普通的操作集合一样(load(), store(), exchange(), compare_exchange_weak(), 和 compare_excha ...
- C++文件流fstream相关操作
C++文件流fstream相关操作 一.理解Open函数 利用fstream,使用open/close打开或创建,完成后关闭,对文件读入读出使用插入器(<<) 或析取器(>>) ...
- String转QString,线段相交,四点共面,git相关操作,截图,扩展工具,string乱码,矩阵相乘
20220513-20220608.QT String转QString 两线段是否相交 四个点是否共面,两个直线是否相交 git相关操作 截图快捷键 shift+win+s VS2013扩展工具不能联 ...
- 基于Ubuntu安装opencv以及相关操作
目录 一.基于Ubuntu下安装opencv 二.相关操作之图片 三.相关操作之视屏 四.总结 五.参考资料 一.基于Ubuntu下安装opencv 1.opencv依赖环境的安装 1.1 安装cma ...
- 【Linux】一篇文章搞定 进程 及相关操作
文章目录 Linux下进程相关操作1. 进程概念1.1 进程基本概念1.2 Linux下PCB的定义2.进程查看3. 进程创建3.1 fork函数3.2 vfork函数3.3 fork与vfork的异 ...
最新文章
- javascript重置(base层)(。。。。不完整)
- 【RocketMQ工作原理】
- ubuntu12.0.4不能正常关机和重启的解决方法
- 怎么学python-初学者如何学习Python?掌握这17个实用小技巧快速入门!
- Linux学习之内核模块编程
- Sqlmap查找SQL注入漏洞入门
- 你觉得一个128g主力机用几年会到非换不可的程度?
- win7 linux启动设置u盘启动,在linux下怎么样制作win7的U盘启动?
- CodeForces 274B Zero Tree :每次选包含1节点的一棵子树,将该子树所有值都+1或者-1最少多少步可以使树值全部为0 :树型dp...
- 第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(昆明),签到题HIL
- if __name__ == __main__如何正确理解
- 编译原理 第3版 第一章练习
- C语言的考试系统,C语言考试系统.doc
- 德州大学计算机系郭小虎2021,2021美国德州农工大学PhD项目
- 缺陷跟踪系统BugTracker。 以下对使用
- 如何做顶级“新生代农民工”?这几本书为你打开大门
- 机器人程序设计入门(C++/Arduino/ROS)(转载2020版)
- Carsim与Simulink联仿Carsim找不到Matlab错误的解决方案,此前装过多个Matlab版本出现该问题可以尝试此方法
- 文件上传(图片上传) 大小限制的配置 及注意点
- 基于IDL的高分二号影像批量预处理程序
热门文章
- 零起点英语_【德国零起点】05—变元音字母
- java 字符串连接_为什么 Java 要把字符串设计成不可变的
- Spring框架错误之org.springframework.beans.factory.BeanCreationException
- php 并发控制中的独占锁
- java查询mongodb 嵌套,查询嵌套文件mongoDB
- php单独使用blade模板引擎,laravel 基础教程 —— Blade 模板引擎
- 解决Exchange用户邮箱别名为乱码的问题
- c++ const
- ORACLE 数据同步时,批量进行新增和更新操作的SQL写法
- php图片合并png保存图片大小,php缩放处理png和jpg图片