[闲聊] 每日C++小秘密(4):I am std::atomic

楼主: yam276 ('_')   2024-10-30 18:57:06
什么是原子操作?
在多执行绪程式中,执行绪之间可能同时访问和修改共享资料。
如果没有适当的同步机制,这可能导致资料竞争和未定义行为。
我们在过去最常使用锁(如 std::mutex)来保护共享资料,
但锁可能带来性能开销和死锁风险。
原子操作提供了一种轻量级的同步方式,
允许我们在不使用锁的情况下进行安全的共享资料访问。
一段使用 std::atomic 的范例:
Code:
#include <atomic>
#include <thread>
#include <vector>
#include <iostream>
std::atomic<int> counter(0);
void increment(int numIncrements) {
for (int i = 0; i < numIncrements; ++i) {
counter.fetch_add(1, std::memory_order_relaxed);
}
}
int main() {
const int numThreads = 4;
const int numIncrements = 100000;
std::vector<std::thread> threads;
for (int i = 0; i < numThreads; ++i) {
threads.emplace_back(increment, numIncrements);
}
for (auto& t : threads) {
t.join();
}
std::cout << "Final counter value: " << counter.load() << std::endl;
// 最终 counter 的值应该是 numThreads * numIncrements
return 0;
}
C++中的 std::atomic
C++11 引入了标准库 <atomic>,提供了一组模板类别和函数,用于实现原子操作。
std::atomic 是一个模板类别,可以包装基本类别或自定义类别,使其操作具有原子性。
原子操作的原理就是确保不会同时有第二个执行绪存取资源,而之所以被称为原子操作,
也是因为原子作为最小不可分割的个体(一般常识上,请忽略夸克等更小的基本粒子),
只要是std::atomic支援的型别与原子性的操作(如store、load、exchange或是运算符号
++,–,+=,-=,&=,|=,^= 等等)就可以进行无锁操作,
但不包含这种单一操作多次使用:
Code:
if (atomicVar.load() == expectedValue) {
atomicVar.store(newValue);
}
因为在 load 与 store 中间可能会有其他原子操作出现。
另外要注意的是内存顺序(memory_order),
因为原子操作可能为了更高效能使用较脆弱的内存顺序(如 memory_order_relaxed)
作者: cities516 (安安路过)   2023-10-30 18:57:00
I am atomic

Links booklink

Contact Us: admin [ a t ] ucptt.com