C++ std::atomic_flag与sta::atomic<bool>布尔标志

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模板似乎加了类似条件变量的功能:

 

std::atomic&lt;bool&gt;是C++标准库中最基本的原子布尔类型。它提供了原子操作来保证对bool变量的并发访问的一致性和线程安全性。与std::atomic_flag相比,std::atomic&lt;bool&gt;具有更强大的功能。它可以使用非原子的bool类型进行构造和赋值,因此可以被初始化为true或false,并且可以从非原子的bool变量赋值给std::atomic&lt;bool&gt;的实例。例如,可以使用以下代码创建并修改std::atomic&lt;bool&gt;变量b: std::atomic&lt;bool&gt; b(true); b = false; 需要注意的是,std::atomic&lt;bool&gt;不是无锁的,为了保证操作的原子性,它的实现中使用了内置的互斥量。但是,在特殊情况下,可以使用is_lock_free()成员函数来检查std::atomic&lt;bool&gt;上的操作是否无锁。这是除了std::atomic_flag之外,所有原子类型都具有的特征。&lt;span class="em"&gt;1&lt;/span&gt;&lt;span class="em"&gt;2&lt;/span&gt;&lt;span class="em"&gt;3&lt;/span&gt; #### 引用[.reference_title] - *1* [C++中的sta::atomicbool>和auto类型](https://blog.csdn.net/weixin_43838785/article/details/123451780)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [5.2.3 std::atomic的相关操作](https://blog.csdn.net/baidu_20351223/article/details/116019312)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

龚建波

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值