C++ release-acquire 与 release sequence 深入解析
1. release-acquire 的核心机制
作用:确保跨线程内存操作的可见性和顺序性。
release:线程A通过原子存储(store)操作发布(publish)数据,并保证该操作前的所有内存操作对其他线程可见。acquire:线程B通过原子加载(load)操作获取数据,并保证该操作后的所有内存操作能观察到线程A的release前的所有修改。
规则:若线程B的acquire加载到线程A的release存储的值,则线程B能观察到线程A在release之前的所有内存操作。
示例:
std::atomic<int> data{0};
std::atomic<bool> ready{false};
// 线程1: 生产数据
void producer() {
data.store(42, std::memory_order_relaxed); // 写入数据
ready.store(true, std::memory_order_release); // 发布数据
}
// 线程2: 消费数据
void consumer() {
while (!ready.load(std::memory_order_acquire)); // 等待数据准备好
assert(data.load(std::memory_order_relaxed) == 42); // 断言成立
}
- ✅
ready的release与acquire建立同步,确保data == 42对消费者可见。
2. release sequence 的扩展同步
定义:在release操作后,若对同一原子变量存在一系列特定操作(属于release sequence),则后续的acquire仍能同步到原release前的操作。
规则:
- 同一线程的后续写入(无论内存顺序)。
- 其他线程的RMW操作(如
fetch_add、compare_exchange_weak)。
示例(正确场景):
std::atomic<int> x{0};
void t1() {
x.store(1, std::memory_order_release); // (1) release操作
x.store(2, std::memory_order_relaxed); // (2) 同一线程写入,属于release sequence
}
void t2() {
int expected = 2;
x.compare_exchange_strong(expected, 3, std::memory_order_relaxed); // (3) RMW操作,属于release sequence
}
void t3() {
while (x.load(std::memory_order_acquire) < 3); // (4) acquire读取到3
assert(x == 1); // ✅ 成立!同步到t1的release操作
}
- ✅
t3的acquire读取到3,属于release sequence,仍能同步到t1的release操作。
3. release sequence 的中断场景
中断条件:若release后的操作不满足以下任一条件,release sequence被破坏:
- 非同一线程的普通写入(如
store(release))。 - 非RMW操作。
错误示例:
std::atomic<int> x{0};
void t1() {
x.store(1, std::memory_order_release); // (1) release操作
}
void t2() {
x.store(2, std::memory_order_release); // (2) 其他线程普通写入,破坏release sequence
}
void t3() {
while (x.load(std::memory_order_acquire) < 2);
assert(x == 1); // ❌ 可能失败!
}
- 🚨
t3的acquire读取到2,但无法保证同步到t1的release操作,导致断言失败。
4. release sequence 的适用范围
| 操作类型 | 是否属于 release sequence | 说明 |
|---|---|---|
| 同一线程的后续写入 | ✅ 是 | 无论内存顺序(如relaxed)。 |
| 其他线程的RMW操作 | ✅ 是 | 如fetch_add、compare_exchange。 |
| 其他线程的普通写入 | ❌ 否 | 如store(release)或store(relaxed)。 |
5. 记忆技巧与关键点
release:相当于“发布信封”,信封内包含之前的所有操作。acquire:相当于“拆开信封”,读取信封内容并保证看到信封内的所有操作。release sequence:若信封在传递过程中未被篡改(仅同一线程或RMW操作修改),则拆信者仍能看到原始内容。
关键点:
- 利用
release-acquire避免数据竞争,确保可见性。 - 确保
release后的操作符合release sequence规则,避免同步失效。
深入理解:
release sequence允许在原子变量被多个线程修改时,仍保持同步链的有效性,前提是修改方式符合规则。- RMW操作通过原子性读取-修改-写入,维持了操作的连续性,因此属于
release sequence。
应用场景:
- 无锁数据结构中的节点发布。
- 多阶段初始化中的状态同步。
📌 正确使用release-acquire和release sequence,是编写高效、正确并发代码的关键!


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



