6、C++内存模型

原文: 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 
#include 
#include 

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

你可能感兴趣的:(C++多线程,c++)