C++ 并发编程指南(11)原子操作 | 11.2、atomic_flag
前言
C++ atomic_flag是C++标准库中的一个原子标志类,用于实现线程间的同步和互斥。它是C++11引入的,提供了一种轻量级的原子操作方式,可以用于实现简单的互斥锁和条件变量等功能。
一、atomic_flag
std::atomic_flag
是 C++11 标准库中的一个类,它提供了一种简单的、无锁的、低开销的原子操作。std::atomic_flag
通常用于那些只需要两个状态的场景,例如作为一个标志或者是一个锁。它只能进行两种操作:设置(clear()
)和清除(test_and_set()
)。
1、特点
- 简单性:
std::atomic_flag
提供了最基础的原子操作,没有提供复杂的比较和交换(compare-and-swap)或加载/存储操作。 - 无锁:使用
std::atomic_flag
可以实现无锁编程,这通常意味着更高的性能,但也可能导致更复杂的代码。 - 低开销:由于
std::atomic_flag
的操作非常简单,所以它的开销通常比其他更复杂的原子类型要小。
2、成员函数
clear()
:将标志设置为false
。test_and_set()
:设置标志为true
,并返回之前的值。test_and_set_explicit()
:与test_and_set()
类似,但可以指定一个内存顺序参数。test_and_reset()
:设置标志为false
,并返回之前的值。test_and_reset_explicit()
:与test_and_reset()
类似,但可以指定一个内存顺序参数。wait()
:等待标志变为false
。notify_one()
:唤醒等待该标志的一个线程。notify_all()
:唤醒等待该标志的所有线程。
3、示例
下面是一个简单的示例,展示了如何使用 std::atomic_flag
来实现一个简单的自旋锁:
#include <atomic>
#include <thread>
#include <iostream>
std::atomic_flag lock = ATOMIC_FLAG_INIT;
void critical_section() {
while (lock.test_and_set()) {
// 如果锁被其他线程持有,则忙等待(自旋)
}
// 临界区代码
std::cout << "Thread " << std::this_thread::get_id() << " is in the critical section.\n";
lock.clear(); // 释放锁
}
int main() {
std::thread t1(critical_section);
std::thread t2(critical_section);
t1.join();
t2.join();
return 0;
}
在这个示例中,两个线程尝试进入临界区。由于使用了
std::atomic_flag
作为锁,所以只有一个线程能够同时进入临界区。当一个线程进入临界区后,它会设置lock
为true
,然后执行临界区代码。当临界区代码执行完毕后,它会将lock
清除为false
,允许其他线程进入临界区。
4、注意事项
std::atomic_flag
的初始值是不确定的,除非你使用ATOMIC_FLAG_INIT
进行初始化。- 由于
std::atomic_flag
的功能非常简单,它可能不适合所有场景。对于更复杂的原子操作,你可能需要使用std::atomic
模板类。 - 在使用
std::atomic_flag
实现自旋锁时,需要注意忙等待(自旋)可能会导致 CPU 资源浪费。在需要等待较长时间的情况下,使用其他类型的锁(如互斥锁)可能更为合适。
原文地址:https://blog.csdn.net/cloud323/article/details/137855029
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!