美文网首页
C++11:多线程内存模型

C++11:多线程内存模型

作者: 重庆八怪 | 来源:发表于2022-05-10 11:06 被阅读0次

先纠正上文的错误,官方版本并未修复,percona版本8.0.27修复。

Innodb的redo模块使用了无锁化编程,为了弥补这片的空缺,通过查询资料和理解,现总结如下:


首先

总的说来对于单线程执行乱序的问题,在多线程之间共享数据的时候,如果想要修改和获取某个数据那么通常的方式就是使用mutex进行线程同步,进而保护临界区资源(也就是共享的内存变量)。但是如果使用了aotm变量那么可以想象aotm变量本生就是一个同步点,想象aotm变量本身就是一个临界区资源修改和访问它必然需要一个同步点。常见的aotm的操作包含

  • load(读取)
  • store(写入)
  • RMW(read-modify-write) 比如常见的compare_exchange_weak(strong)

如果以这个同步点为(Synchronizes-with)为中心发散,就出现了几种内存模型:

  • 顺序一致(sequentially consistent ordering)

memory_order_seq_cst:原子操作的前置读写, 不往后排, 后置读写, 不往前排.

  • 获取发布 (acquire-release ordering)
    memory_order_consume:类似于memory_order_acquire,也是用于load操作,但更为宽松,不做讨论。

memory_order_release(store写入):写原子操作的前置写操作不重排到该写操作的后面。写barrier生效, 则前置写也生效。

memory_order_acquire(load读取):读原子操作的后置读操作不重排到该读操作的前面。读barrier生效, 也后置读也生效。

memory_order_acq_rel(read-modify-write):操作前后的语句都不允许跨越该操作而重排。该操作相当于兼具load(acquire)和store(release),可以看作由这两个操作组成,但是整体上是原子的。

  • 松散(relaxed ordering )

memory_order_relaxed : 仅仅保证aotm变量这个同步点,不进行任何重排,没有barrier属性,这种方式通常用于计数器。

实际上常用的就是:

  • memory_order_release和memory_order_acquire的成对出现

这种操作能够提供以同步点为中心,release(store写入)的时候,保证线程A其前面的变量的修改(代码)都已经修改完成,并且acquire(load读取)的时候,保证线程B后面读取操作(代码)都是在其之后,

   A                               B

  b=10;(一定在之前)
--aotm变量release              --aotm变量 acquire      ---->aotm变量就是一个同步点
(store写入)                    (load读取)
                               cout<<b<<endl;(一定在之后)
  • memory_order_acq_rel单独出现,这个功能类似上面的,感觉更强,因为它兼备了load(acquire)和store(release)

其次

我们也可以使用 aotmic_thread_fence,进行显示插入内存屏障,同样对于内存模型也有如上的类型,比如memory_order_release和memory_order_acquire,但是应用范围更广,对于基于原子变量的release opration,仅仅是阻止前面的内存操作重排到该release opration之后,而release fence则是阻止重排到fence之后的任意store operation之后。比如

aotmv1=false
aotmv2=false

T1:
b = 10;
fence(memory_order_release);
aotmv1.store(true,memory_order_relaxed ); -- 同步点
aotmv2.store(true,memory_order_relaxed ); -- 同步点
那么代表atomv2之前的操作都已经完成

T2:
fence(memory_order_acquire);
while(!aotmv1.load(memory_order_relaxed ) ); --同步点 增加while 循环确认
while(!aotmv2.load(memory_order_relaxed ));-- 同步点 增加while 循环确认
assert(b != 0)
拿表代表aotmv2之后的操作一定在之后,那么b一定等于10,断言是成功的

这里增加while循环的原始是确认T1的更改已经做了,否则T2的操作可能更快,aotmv1和aotmv2还是初始值false。

参考资料:
C++ concurrentcy in action
https://www.zhihu.com/question/24301047
https://zhuanlan.zhihu.com/p/382372072
https://blog.csdn.net/baidu_20351223/article/details/116126731

相关文章

  • 原子类型与原子操作

    原子类型和原子操作 并行编程、多线程与C++11 常见的并行编程有多种模型:共享内存、多线程、消息传递等。 多线程...

  • 原子操作内存序

    [TOC] 参考 1. C++11多线程-内存模型2. c++并发编程1.内存序3. 浅谈Memory Reord...

  • C++11多线程-内存模型

    我们在前面讲atomic时,每一个原子操作都有一个std::memory_order参数。这个参数就是C++11的...

  • C++11:多线程内存模型

    先纠正上文的错误,官方版本并未修复,percona版本8.0.27修复。 Innodb的redo模块使用了无锁化编...

  • C++11 Memory Model

    Herb Sutter在一次对C++11内存模型的演讲中提到C++11的内存模型,让C++有了标准独立于编译器和平...

  • C++内存模型

    内存模型是多线程环境能够可靠工作的基础,因为内存模型需要对多线程环境的运作细节进行完备的定义。 内存模型通过共享数...

  • 深入理解Java并发内存模型

    Java内存模型是什么 Java 内存模型翻译自Java Memory Model,也称Java多线程内存模型,简...

  • java并发编程(四)

    java多线程编程(四) 引言: 内存模型的基础----内存模型相关的基本概念 java内存模型中的顺序一致性--...

  • java内存模型

    前言 在学习java多线程并发编程前,必须要了解java内存模型,只有了解java内存模型,才能知道为什么多线程并...

  • (五) volatile关键字

    Java多线程目录 1 背景 理解Java多线程的内存抽象逻辑请阅读java多线程内存模型,当代操作系统,处理器为...

网友评论

      本文标题:C++11:多线程内存模型

      本文链接:https://www.haomeiwen.com/subject/bxrlurtx.html