6、C++内存模型

文章详细介绍了C++11开始支持的多线程中关于atomic类型和memory_order的不同模式,如sequentially_consistent保证了跨线程的可见性,relaxed仅保证读写的完整性,而acquire/release模式则用于线程间的同步。通过示例代码解释了这些模式在并发编程中的应用和重要性。
摘要由CSDN通过智能技术生成

原文: https://my.oschina.net/u/2516597/blog/805489

背景

C++11开始支持多线程,其中提供了原子类型atomic, 和atomic关系比较密切的是memory_order,所有的内存模型都是指atomic类型

enum memory_order {
    memory_order_relaxed,
    memory_order_consume,
    memory_order_acquire,
    memory_order_release,
    memory_order_acq_rel,
    memory_order_seq_cst
};a

具体

std::memory_order_seq_cst

首先是最严格的模型sequentially consistent, 下面的代码可以保证assert一定正确。

 -Thread 1-       -Thread 2-
 y = 1            if (x.load() == 2)
 x.store (2);        assert (y == 1)

这里的store和load没有显示指定model的话,默认就是std::memory_order_seq_cst,该模式保证如果在线程2中拿到x在1中存储的值,那么线程2就可以在这看到线程1中所有发生在x.store(2)之前操作(主要是就是写操作),即使变量和x没有关系,是不是atmoic也无所谓,对于线程2来说,都是可见的。(有点疑惑,这和acquire和release有啥区别)

std::memory_order_relaxed

该模式仅仅保证了读写的完整性(不会读取到写一半的数据,要么是新值,要么是旧值),以及该原子的修改顺序一致性。

#include <atomic>
#include <thread>
#include <cassert>

std::atomic<bool> x,y;
std::atomic<int> z;

void write_x_then_y()
{
  x.store(true,std::memory_order_relaxed);  // 1
  y.store(true,std::memory_order_relaxed);  // 2
}
void read_y_then_x()
{
  while(!y.load(std::memory_order_relaxed));  // 3
  if(x.load(std::memory_order_relaxed))  // 4
    ++z;
}
int main()
{
  x=false; //5
  y=false; //6
  z=0; //7
  std::thread a(write_x_then_y); //A
  std::thread b(read_y_then_x);  //B
  a.join();
  b.join();
  assert(z.load()!=0);  // 8

  return 0;
}

assert是仍然有可能触发的! 內存模型是std::memory_order_relaxed, 根据这个内存模型的说明,1,2处可能乱序,5,6和7也可能重拍乱序。所以在3和4处的read操做就可能即便y load到了true, 而x仍然load到false.
再举一个例子:下面的assert就不能出错。因为该原子在线程1中的顺序一定是正确的。

-Thread 1-
x.store (1, memory_order_relaxed)
x.store (2, memory_order_relaxed)

-Thread 2-
y = x.load (memory_order_relaxed)
z = x.load (memory_order_relaxed)
assert (y <= z)
std::memory_order_acquire/release

这个模式上面两个模式的混合, 下面的代码是x,y初始值都是0,在该模式下两个assert是可以通过的,但是如果不使用该模式的话,肯定只能通过,好好理解这个东西

 -Thread 1-
 y.store (20, memory_order_release);

 -Thread 2-
 x.store (10, memory_order_release);

 -Thread 3-
 assert (y.load (memory_order_acquire) == 20 && x.load (memory_order_acquire) == 0)

 -Thread 4-
 assert (y.load (memory_order_acquire) == 0 && x.load (memory_order_acquire) == 10)
参考

https://gcc.gnu.org/wiki/Atomic/GCCMM/AtomicSync

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值