添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
彷徨的热水瓶  ·  Visual Studio 中的 ...·  11 月前    · 
可爱的木耳  ·  探索开源FastChat ...·  1 年前    · 
闷骚的弓箭  ·  Python求助:34, ...·  1 年前    · 
坏坏的板栗  ·  JavaScript: What's ...·  1 年前    · 

1.std::atomic_flag

std::atomic_flag是最简单的标准原子类型,他代表一个布尔标识,没有拷贝构造函数和拷贝赋值运算符(=delete)。

std::atomic_flag对象可以是两种状态之一:设置或清除,且必须用ATOMIC_FLAG_INIT初始化,这会将该标志初始化为清除状态(此标志总是以清除状态初始化的),如下:

std::atomic_flag flag=ATOMIC_FLAG_INIT;

一旦标识对象初始化完成,只能做三种操作:销毁、清除或设置并查询其先前的值。这些分别对应析构函数、clear()函数以及test_and_set()函数。clear和test_and_set操作都可以指定一个内存顺序,clear是存储操作,test_and_set是读改写操作,指定内存顺序相关参见C++在线文档 https://zh.cppreference.com/w/cpp/atomic/memory_order

在原子类型上的每一个操作均具有一个可选的内存顺序参数,它可以用来指定所需的内存顺序语义。
存储(store)操作: 可以包括memory_order_relaxed、memory_order_release、memory_order_seq_cst顺序。
载入(load)操作: 可以包括memory_order_relaxed、memory_order_consume、memory_order_acquire、memory_order_seq_cst顺序。
读改写(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。

C++在线手册上提供了一个实现自旋锁得例子:

#include <thread>
#include <vector>
#include <iostream>
#include <atomic>
std::atomic_flag lock = ATOMIC_FLAG_INIT;
void f(int n)
	for (int cnt = 0; cnt < 5; ++cnt) {
		while (lock.test_and_set(std::memory_order_acquire))  // 获得锁
			; // 自旋
		std::cout << "Thread " << n << " count:" << cnt << std::endl;
		lock.clear(std::memory_order_release);               // 释放锁
int main(int argc, char* argv[])
	std::vector<std::thread> v;
	for (int n = 0; n < 4; ++n) {
		v.emplace_back(f, n); //使用参数进行初始化
	for (auto& t : v) {
		t.join(); //等待线程结束
	system("pause");
	return 0;

运行结果如下:

std::atomic_flag由于限制性甚至不能用作一个通用的布尔标识,因为它不具有简单的无修改查询操作,最好还是使用std::atomic<bool>。(貌似我也用不到std::atomic_flag)

2.sta::atomic<bool>

最基本的原子整数类型是std::atomic<bool>(可以使用预定义的别名std::atomic_bool),这是一个比std::atomic_flag功能更全的布尔标志,并且可以使用非原子的bool来赋值和初始化。

std::atomic<bool> b(true);
b=false;

要注意的是,原子类型赋值操作返回值而非引用。

与std::atomic_flag使用clear不同,std::atomic<bool>写(存储)操作是通过store来完成的;test_and_set也由exchange函数替代,它可以用新值替代原值,同时获取原值。std::atomic<bool>支持对值得无修改查询,通过隐式转换为普通得bool,或者调用load函数,load是一个载入操作。

std::atomic<bool> b;
bool x=b.load(std::memory_order_require);
b.store(true);
x=b.exchange(false,std::memory_order_acq_rel);

在C++20,std::atomic模板似乎加了类似条件变量的功能:

atomic_boolC++ 中的一种原子类型,它是 bool 类型的原子版本。它可以用来在多线程环境下进行原子操作,避免了竞态条件和死锁的发生。 使用方法类似于普通 bool 类型,可以进行赋值、比较和逻辑运算。同时,还支持原子操作,如 compare_exchange_weak() 和 exchange() 等。 std::atomic_boolflag; flag.store(... 所谓的原子操作,取的就是“原子是最小的、不可分割的最小个体”的意义,它表示在多个线程访问同一个全局资源的时候,能够确保所有其他的线程都不在同一时间内访问相同的资源。也就是他确保了在同一时刻只有唯一的线程对这个资源进行访问。这有点类似互斥对象对共享资源的访问的保护,但是原子操作更加接近底层,因而效率更高。 在以往的C++标准中并没有对原子操作进行规定,我们往往是使用汇编语言,或者是借助第三方的 文章目录sta::atomicauto类型用法总结 sta::atomic 最基本的原子整数类型是std::atomic(可以使用预定义的别名std::atomic_bool),这是一个比std::atomic_flag功能更全的布尔标志,并且可以使用非原子的bool来赋值和初始化。 std::atomic&lt;bool&gt; b(true); b=false; 要注意的是,原子类型赋值操作返回值而非引用。 与std::atomic_flag使用clear不同,std::atomic写(存储)操作是 上文讲述了最简单的原子标识,本文讲讲 std::atomic 原子布尔类。相比较 std::atomic_flag ,原子布尔类有更多的操作。原子布尔类操作大都比较简单,只是比较交换操作较难理解,需要多学多练。 5.2.3 std::atomic的相关操作 最基本的原子整型类型就是 std::atomic&lt;bool&gt; 。如你所料,它有着比 std::atomic_flag更加齐全的布尔标志特性。虽然它依旧不能拷贝构造和拷贝赋值,但是你可以使用一个非原子的bool类型构造它,所以它可以被初始化为true或false,并且你也可以从一个非原子bool变量赋值给 std::atomic&lt;bool&gt; 的实例: std::atomic&lt;bool&gt; b(true); b = false 在C++11之前,涉及到多线程问题,都是和平台相关的,比如windows和Linux下各有自己的接口,这使得代码的可移植性比较差。C++11中最重要的特性就是对线程进行支持了,使得C++在并行编程时不需要依赖第三方库,而且在原子操作中还引入了原子类的概念。要使用标准库中的线程,必须包含< thread >头文件。 5.2.3 std::atomic的相关操作 最基本的内置类型就是std::atomic,这是个比atomic_flag更为全面的bool量。尽管它仍然不支持拷贝构造和拷贝赋值,但是它可以从一个非原子类型的bool量构造,也可以用一个非原子类型来给std::atomic赋值: std::atomic b(true); b=false; 需要注意的是,复制操作并不像我们平时那样返回对象引用,而 以下代码利用atomic实现了一个轻量级的读写资源锁,保证有线程在读取时,写入线程阻塞,当写入线程执行时,所有的读取线程都被阻塞,并且可以根据需要通过构造函数参数设置读/写优先,且locck/unlock语句允许嵌套,相比利用互斥锁实现的读写锁,本锁更类似自旋锁 lock.readLock(); lock.readLock(); C++11在实现自旋锁时,一般会用atomic_flag来实现,它有两个成员函数:test_and_set()和clear(),看cppreference上的解释看了一头雾水,所以自己在vs里debug了一下。 #include &lt;iostream&gt; #include &lt;atomic&gt; using namespace std; int main() { std::atomic_flag flag{ ATOMIC_FLAG_INIT }; cout &lt;&lt; flag. 本文介绍 &lt; atomic &gt; 头文件中最简单的原子类型: atomic_flagatomic_flag 一种简单的原子布尔类型,只支持两种操作,test-and-set 和 clear。 std::atomic_flag 构造函数 std::atomic_flag 构造函数如下: atomic_flag() noexcept = default; atomic_flag (const atomic_flag&T) = delete; std::atomic_flag 只有默认构造 内存顺序模型 有六种内存顺序选项可以应用到原子类型上, memory_order_relaxed;memory_order_consume; memory_order_acquire;memory_order_release;memory_order_acq_rel; memory_order_seq_cst; 它们代表三种模型: 顺序一致 memory_order_seq_cst; 获得-释放:memory_order_consume; memory_order_acquire;memory_orde