原子操作保证单个变量的读写不可中断,内存顺序控制多线程下操作的可见性与顺序,二者结合可在无锁情况下实现高效、正确的并发编程。

C++的原子操作和内存顺序,在我看来,是多线程编程里一把双刃剑,它能让你在无锁并发的世界里翩翩起舞,也能在你一个不慎时,把你摔得七荤八素。简单来说,原子操作保证了单个变量的读写或修改是不可中断的,就像一个事务,要么完成,要么不发生。而内存顺序(
memory_order
要深入理解并运用C++的原子操作与内存顺序,我们首先得认识到它们是为了解决传统锁机制(如
std::mutex
std::atomic
核心在于
std::atomic<T>
T
memory_order
memory_order
立即学习“C++免费学习笔记(深入)”;
memory_order_relaxed
memory_order_consume
acquire
memory_order_acquire
acquire
release
memory_order_release
release
acquire
memory_order_acq_rel
acquire
release
memory_order_seq_cst
seq_cst
std::atomic
实际应用中,我们通常会结合
load()
store()
exchange()
compare_exchange_weak()
compare_exchange_strong()
fetch_add()
#include <atomic>
#include <thread>
#include <vector>
#include <iostream>
std::atomic<int> counter(0); // 默认memory_order_seq_cst
void increment_counter() {
for (int i = 0; i < 10000; ++i) {
counter.fetch_add(1, std::memory_order_relaxed); // 简单计数,不需要严格顺序
}
}
std::atomic<bool> ready(false);
std::atomic<int> data(0);
void producer() {
data.store(42, std::memory_order_release); // 写入数据,并释放内存顺序
ready.store(true, std::memory_order_release); // 设置就绪标志,并释放内存顺序
}
void consumer() {
while (!ready.load(std::memory_order_acquire)) { // 等待就绪,并获取内存顺序
std::this_thread::yield(); // 避免忙等
}
// 此时,data.load()将保证看到42,因为ready的acquire与producer的release同步
std::cout << "Data is: " << data.load(std::memory_order_relaxed) << std::endl;
}
int main() {
std::vector<std::thread> threads;
for (int i = 0; i < 10; ++i) {
threads.emplace_back(increment_counter);
}
for (auto& t : threads) {
t.join();
}
std::cout << "Final counter: " << counter.load() << std::endl; // 默认seq_cst加载
std::thread p(producer);
std::thread c(consumer);
p.join();
c.join();
return 0;
}这确实是个好问题,初学者往往会疑惑,既然有
std::mutex
普通锁(互斥量)的粒度通常比较粗。它保护的是一段代码块,也就是所谓的“临界区”。当一个线程进入临界区时,它会获得锁,其他试图进入的线程就必须等待。这种机制简单有效,能确保临界区内的所有操作都是串行执行的,从而避免数据竞争。然而,它的缺点也很明显:
原子操作则提供了一种“无锁(lock-free)”或“非阻塞(non-blocking)”的并发控制手段。它主要针对单个变量的读、写、修改操作。CPU提供了特殊的指令(例如,x86架构上的
LOCK
对比来看:
当然,原子操作并非万能药。它们只适用于单个变量的操作。如果需要保护多个变量或复杂的复合操作,那么锁仍然是更直接、更安全的方案。原子操作的复杂性在于,一旦脱离了默认的
seq_cst
memory_order
C++内存模型这东西,坦白说,初次接触时会让人觉得有点玄乎,它描述的是多线程程序中,内存操作的可见性和顺序性规则。不同的
memory_order
std::memory_order_relaxed
relaxed
relaxed
relaxed
std::atomic<int> x(0);
std::atomic<int> y(0);
void thread1() {
x.store(1, std::memory_order_relaxed);
y.store(1, std::memory_order_relaxed); // y可能在x之前被其他线程看到
}
void thread2() {
while (y.load(std::memory_order_relaxed) == 0); // 等待y被写入
// 此时x.load()可能仍为0,因为relaxed不提供排序保证
if (x.load(std::memory_order_relaxed) == 0) {
std::cout << "Surprise! x is still 0 even after y is 1." << std::endl;
}
}std::memory_order_release
std::memory_order_acquire
release
release
acquire
acquire
release
release
acquire
acquire
release
release
acquire
std::atomic<int> data_item(0);
std::atomic<bool> data_ready(false);
void producer_thread() {
data_item.store(100, std::memory_order_relaxed); // 写入数据
data_ready.store(true, std::memory_order_release); // 释放,确保data_item可见
}
void consumer_thread() {
while (!data_ready.load(std::memory_order_acquire)) { // 获取,等待data_ready为true
std::this_thread::yield();
}
// 此时,data_item.load()保证能看到100
std::cout << "Consumed: " << data_item.load(std::memory_order_relaxed) << std::endl;
}std::memory_order_acq_rel
acquire
release
fetch_add
compare_exchange
acquire
counter.fetch_add(1, std::memory_order_acq_rel);
counter
acquire
release
std::memory_order_seq_cst
seq_cst
seq_cst
seq_cst
seq_cst
std::atomic
seq_cst
std::memory_order_consume
acquire
consume
consume
acquire
acquire
consume
acquire
选择正确的
memory_order
seq_cst
acq_rel
acquire/release
relaxed
在我看来,原子操作和内存顺序就像是精密的手术刀,用好了能切中要害,效率奇高;用不好,就可能伤及无辜,甚至导致整个系统崩溃。这里列举一些我在实践中遇到或观察到的常见陷阱:
忘记原子性:将std::atomic
std::atomic<int> value;
int temp = value;
value = temp + 1;
value.load()
value.store()
value.fetch_add()
int
std::atomic
memory_order_relaxed
relaxed
relaxed
A
B
A
B
A
B
B
A
A
A
B
data
flag
flag
data
data
flag
relaxed
flag
data
relaxed
误解acquire/release
acquire/release
release
acquire
release
acquire
release
acquire
以上就是C++原子操作与内存顺序memory_order使用的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号