一、原子操作简介
在多线程编程中,通常我们需要多个线程共享数据。但如果不加以控制,多个线程同时访问同一数据,可能会导致数据不一致或竞争条件(race conditions)。为了解决这个问题,我们引入了 原子操作。
原子操作 是指在执行时不会被中断、打断或修改的操作。换句话说,原子操作要么完全执行,要么完全不执行,不会在中间被其他线程的操作干扰。这种特性对于多线程环境中的数据访问是至关重要的。
C++11 引入了 <atomic> 库,它提供了对原子操作的支持。通过这个库,我们可以确保在多线程环境中对数据的访问不会导致竞争条件。
二、C++ 原子操作的基本概念
在 C++ 中,原子操作的关键是 原子类型(atomic types)。原子类型是由 std::atomic 模板类提供的,它包装了一个类型,确保对该类型的所有操作(如读取、写入、更新等)都是原子的。
关键概念
- 原子类型 (
std::atomic):可以包装任何基本类型(如int、bool、float等),并保证对这些类型的操作是原子的。 - 原子操作:对原子变量的操作是不可分割的,意味着在多线程中不会被打断。
- 原子变量:一个变量可以被声明为原子类型(如
std::atomic<int>),它保证在多线程环境下对该变量的操作是安全的。
常用的原子操作
- load:读取原子变量的值。
- store:将一个值存储到原子变量中。
- exchange:将原子变量的值替换为一个新值,并返回旧值。
- compare_exchange_weak / compare_exchange_strong:原子地进行条件交换操作。若当前值等于预期值,则交换新值。
- fetch_add / fetch_sub:原子地执行加法或减法操作,并返回旧值。
三、std::atomic 类模板
std::atomic 是一个模板类,可以用于包装基础数据类型,确保对该数据类型的所有操作都是原子性的。
基本使用
#include <iostream>
#include <atomic>
#include <thread>
#include <vector>
using namespace std;
std::atomic<int> counter(0);
void increment() {
for (int i = 0; i < 100000; ++i) {
counter.fetch_add(1, std::memory_order_relaxed); // 原子递增
}
}
int main() {
std::vector<std::thread> threads;
for (int i = 0; i < 4; ++i) {
threads.push_back(std::thread(increment)); // 启动4个线程
}
for (auto& t : threads) {
t.join(); // 等待线程完成
}
cout << "Counter value: " << counter.load() << endl; // 输出最终结果
return 0;
}
常用原子操作的详细介绍
1. load() 和 store()
load():从原子变量读取值。store():将值存储到原子变量中。
std::atomic<int> a(
C++ atomic 原子操作详解与应用

最低0.47元/天 解锁文章
558

被折叠的 条评论
为什么被折叠?



