一、概述
C原子操作是C 11标准引入的一个新的特性,用于确保多线程环境下的线程安全性。原子操作是一个不可分割的操作,能够确保被多个线程同时访问的变量能够正确地同步。原子操作提供了一种高效的、易用的方式来处理共享数据。
二、原子变量
原子变量是一种特殊类型的变量,多个线程可以同时访问它。原子变量的操作是原子的,即对一个原子变量的操作不可被打断,也不会被其他线程所干扰。C++语言中定义了原子变量类型std::atomic
,原子变量的操作可以通过std::atomic<>
模板进行实现。
#include <atomic>
std::atomic<int> counter{0}; //定义一个原子变量
counter++; //原子递增操作
以上代码定义了一个原子变量counter
,并对其进行了递增的操作。由于递增操作是原子的,因此可以确保在多线程环境下,对counter
的递增操作不会被打断。
三、原子操作类型
C++标准库定义了几种常用的原子操作类型,包括:
1. std::memory_order
std::memory_order
是一个枚举类型,用于指定内存序(memory order),即原子操作的执行顺序。
enum class memory_order {
relaxed, //松散的内存模型,不对内存序做任何保证
consume, //对读操作的顺序做保证,对写操作没有任何保证
acquire, //对读操作的顺序做保证,对写操作没有任何保证
release, //对写操作的顺序做保证,对读操作没有任何保证
acq_rel, //对读/写操作的顺序做保证
seq_cst //对读/写操作和其他原子操作的顺序做保证,严格的内存模型
};
2. std::atomic_flag
std::atomic_flag
是一个特殊的原子变量类型,只能够进行原子的测试和设置操作。std::atomic_flag
类型可以用于实现自旋锁。
#include <atomic>
std::atomic_flag lock = ATOMIC_FLAG_INIT; //初始化std::atomic_flag
lock.test_and_set(); //原子测试并设置操作
lock.clear(); //原子清除操作
3. std::atomic_bool
std::atomic_bool
是一个原子布尔变量类型,可以进行原子的加载、存储和交换操作。
#include <atomic>
std::atomic_bool flag{false}; //定义一个std::atomic_bool变量
bool temp = flag.exchange(true); //原子交换操作
4. std::atomic_integral
std::atomic_integral
是一个原子整数变量类型,可以进行原子的加载、存储、交换、递增、递减等操作。
#include <atomic>
std::atomic<int> counter{0}; //定义一个std::atomic<int>变量
counter++; //原子递增操作
int temp = counter.fetch_add(10); //原子加法操作,并返回原先的值
四、原子操作的实现原理
原子操作的实现主要依赖于硬件体系结构提供的特殊指令(CPU指令)。这些特殊指令可以确保对共享变量的操作是原子的,即不可分割的,或者是具有一定的同步语义的。 在x86体系结构下,常用的原子操作命令包括:
lock cmpxchg
:用于原子比较并交换操作lock xchg
:用于原子交换操作lock add/sub
:用于原子加法/减法操作 当CPU执行原子操作时,它会锁定访问操作的内存位置,并禁止其他CPU修改该位置的值。当原子操作完成后,CPU会释放对该内存位置的锁定,并允许其他CPU修改该位置的值。
五、多线程编程中的原子操作示例
下面的代码示例演示了原子操作在多线程编程中的使用,其中包括std::atomic_bool
的测试和设置操作、std::atomic_int
的递增操作,以及std::atomic_flag
的设置和清除操作。
#include <iostream>
#include <thread>
#include <atomic>
std::atomic_bool flag{false};
std::atomic_flag lock = ATOMIC_FLAG_INIT;
std::atomic_int counter{0};
void thread_func() {
lock.test_and_set(); //原子测试并设置lock
if (!flag) {
flag = true; //原子设置flag
std::cout << "Thread " << std::this_thread::get_id() << " sets the flag." << std::endl;
}
lock.clear(); //原子清除lock
counter++; //原子递增
std::cout << "Thread " << std::this_thread::get_id() << " increases the counter to " << counter << "." << std::endl;
}
int main() {
std::thread t1(thread_func);
std::thread t2(thread_func);
t1.join();
t2.join();
return 0;
}
运行该程序,可以看到两个线程分别进行了原子操作,并保证了线程安全。
六、总结
本文对C++原子操作进行了详细的介绍,包括原子变量、原子操作类型、原子操作的实现原理以及在多线程编程中的应用。借助于原子操作,程序员可以轻松地处理共享数据的同步,从而提高程序的并发性能。