c++11 memory model

C++11内存模型针对编译器优化、CPU乱序执行和Cache重排可能导致的问题,规定了内存操作的可见性。其中,relaxed语义允许自由优化,release-acquire语义确保线程间特定顺序的可见性,而memory_order_seq_cst语义保证全局一致的顺序。理解这些内存语义对于多线程编程至关重要。
摘要由CSDN通过智能技术生成

为什么需要memory order

  • 编译器出于优化的目的,在编译阶段将源码的顺序进行交换。
  • 程序执行期间,指令流水被CPU乱序执行。
  • Cache的分层及刷新策略使得有时候某些写,读操作的顺序被重排。
  • 原子操作说的是,一个操作的状态要么就是未执行,要么就是已完成,不会看见中间状态。

内存模型

内存模型所要表达的内容主要是这么描述: 一个内存操作的效果,在其他线程中的可见性问题
C++11 中的 atomic library 中定义了以下6种语义来对内存操作的行为进行约定,这些语义分别规定了不同的内存操作在其它线程中的可见性问题:

memory_order {
  memory_order_relaxed, 
  memory_order_consume,
  memory_order_acquire,
  memory_order_release,
  memory_order_acq_rel,
  memory_order_seq_cst
};
  1. relaxed语义:当对公共变量以 relaxed 方式进行读写时,编译器,cpu 等是被允许按照任意它们认为合适的方式来加以优化处理的。
  2. release-acquire 语义:如果一个线程A对一块内存 m 以 release 的方式进行写操作,那么在线程 A 中,所有在该 release 操作之前进行的内存写操作,都在另一个线程 B 对内存 m 以 acquire 的方式进行读操作后,变得可见。
#include <thread>
#include <atomic>
#include <cassert>
#include <string>
std::atomic<bool> ready{ false };
int data = 0;
void producer()
{
    data = 100;                                       // A
    ready.store(true, std::memory_order_release);     // B
}
void consumer()
{
    while (!ready.load(std::memory_order_acquire));    // C
    assert(data == 100); // never failed              // D
}
int main()
{
    std::thread t1(producer);
    std::thread t2(consumer);
    t1.join();
    t2.join();
    return 0;
}
  • 首先 A 不允许被移动到 B 的后面。

  • 同样 D 也不允许被移动到 C 的前面。

  • 当 C 从 while 循环中退出了,说明 C 读取到了 B store()的那个值,此时,Thread-2 保证能够看见 Thread-1 执行 B 之前的所有写入操作(也即是 A)。

  1. memory_order_seq_cst语义:对所有以 memory_order_seq_cst 方式进行的内存操作,不管它们是不是分散在不同的 cpu 中同时进行,这些操作所产生的效果最终都要求有一个全局的顺序,而且这个顺序在各个相关的线程看起来是一致的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值