memory model

最近看C++11 atomic发现对memory_order很是不理解,memory_order_relaxed/memory_order_consume/memory_order_acquire/memory_order_release/memory_order_acq_rel/

memory_order_seq_cst。这些都是跟memory model有关

关于memory model,对于线程来说,其实是跟编译器相关的。因为我们的编译器在把C++语言翻译成机器代码的时候,会进行各种优化。

我们做C++ GDB的时候,我们会发现,当我们使用-O2优化后,我们再调试的时候,发现程序的执行顺序根本就不是我们写的时候,我们想象的执行顺序。这样优化是有好处的,可以大大提高我们程序的运行速度,但是这样也不是都是好的(volatile类型不建议使用的原因,就是跟这个有关),这些优化都是建立在一个线程上进行的。所以在多线程的时候就要考虑优化造成的问题。

为了不让编译器在做优化的时候,不因为编译器的优化错误,而使程序错误,这就需要acquire/release原语。。

release时,编译器保证不会把写操作移到它后边,否则其他线程就看不到这个修改了;

acquire时,不会把其后的读操作移到它前面,否则读到的就是旧数据。

剩下的情况,编译器就可以自由移动读写操作

而在C++11

memory_order_acquire

Acquire operation:

      no reads in the current thread can be reordered before this load.

      This ensures that all writes in other threads that release the same atomic variable are visible in the current thread

Acquire 操作:

      在当前线程中,所有的read操作的乱序,不能出现在这个atomic变量load之前。(意思就是在当前线程中,编译器或者cpu在优化代码的时候,

      不能把读操作的代码出现在这个变量之前)

      这保证所有的write在当前线程中是可以得到的,当然前提是在其他线程中共用这个atomic的变量的,应该释放这个atmic变量(意思就是:保证

      所有的写操作都是有效的,防止在优化后,出现“已经读完了,但是还没写”的情况出现。)

memory_order_release:

Release operation:

        no writes in the current thread can be reordered after this store.

        This ensures that all writes in the current thread are visible in other threads that acquire the same atomic variable.

memory_order_relaxed: 说明这个操作除了是原子的外,周围的操作随便移动,比较适合做计数器

memory_order_acq_rel基本是memory_order_acquire和memory_order_release的合体

memory_order_scq_cst是memory_order_acq_rel的加强版, atomic默认是这个

memory_order_consume是memory_order_acquire的弱化版,它只保证不把跟当前load的变量有依赖的变量reorder,没依赖关系的随便移动

参考资料:

1 . 浅谈Memory Reordering

2. 透过LINUX内核看无锁编程

3. Why the "volatile" type class should not be used

时间: 2024-10-12 15:08:03

memory model的相关文章

java学习:JMM(java memory model)、volatile、synchronized、AtomicXXX理解

一.JMM(java memory model)内存模型 从网上淘来二张图: 上面这张图说的是,在多核CPU的系统中,每个核CPU自带高速缓存,然后计算机主板上也有一块内存-称为主内(即:内存条).工作时,CPU的高速缓存中的数据通过一系列手段来保证与主内的数据一致(CacheCoherence),更直白点,高速缓存要从主内中load数据,处理完以后,还要save回主存. 上图说的是,java中的各种变量(variable)保存在主存中,然后每个线程自己也有自己的工作内存区(working me

C# Memory model

Memory Model http://blogs.msdn.com/b/cbrumme/archive/2003/05/17/51445.aspx C# - The C# Memory Model in Theory and Practice https://msdn.microsoft.com/magazine/jj863136 https://msdn.microsoft.com/en-us/magazine/jj883956.aspx

CUDA ---- Memory Model

Memory kernel性能高低是不能单纯的从warp的执行上来解释的.比如之前博文涉及到的,将block的维度设置为warp大小的一半会导致load efficiency降低,这个问题无法用warp的调度或者并行性来解释.根本原因是获取global memory的方式很差劲. 众所周知,memory的操作在讲求效率的语言中占有极重的地位.low-latency和high-bandwidth是高性能的理想情况.但是购买拥有大容量,高性能的memory是不现实的,或者不经济的.因此,我们就要尽量

Deep Analysis Java Memory Model

提纲: •Java内存模型 •volatile关键字 •long和double变量的特殊规则 •原子性,可见性与有序性 •先行发生原则 •Java与线程 1.java内存模型 Java虚拟机规范中试图定义一种java内存模型(Java Memory Model,JMM)来屏蔽掉各种硬件和操作系统的内存访问差异,以实现让Java程序在各种平台上都能达到一致的内存访问效果. 主内存与工作内存: JMM的主要目标是定义了程序中各个变量的访问规则,及虚拟机中将变量存储到内存和从内存中取出变量的底层细节.

还是说Memory Model,gcc的__sync_synchronize真是太坑爹了

还是说Memory Model,gcc的__sync_synchronize真是太坑爹了! 时间 2012-01-29 03:18:35  IT牛人博客聚合网站 原文  http://www.udpwork.com/item/6751.html 主题 GCC 嗯,还是说可见性的问题.由于CPU和编译器的乱序执行功能,我们经常不得不在代码中手动插入memory barrier.如果你还不清楚memory barrier是什么,那么请先读这个 http://en.wikipedia.org/wiki

Keil中Memory Model和Code Rom Size说明

源:Keil中Memory Model和Code Rom Size说明 C51中定义变量时如果省略存储器类型,Keil C51编译系统则会按编译模式SMALL.COMPACT和LARGE所规定的默认存储器类型去指定变量的存储区域,无论什么存储模式都可以声明变量在任何的8051存储区范围i,但是把最常用的命令如循环计数器和队列索引放在内部数据区可以显著地提高系统性能.以下介绍一下Keil编译选项Target中的Memory Model和Code Rom Size的设置. Memory Model(

当我们在谈论JMM(Java memory model)的时候,我们在谈论些什么

前面几篇中,我们谈论了synchronized.final以及voilate的用法和底层实现,都绕不开一个话题-Java内存模型(java memory model,简称JMM).Java内存模型是保证线程安全的基础,主要描述了程序中全序的同步动作在不同线程访问共享全局变量时所体现的原子性.可见性和有序性上的限制. 1.定义 维基百科定义:The Java memory model describes how threads in the Java programming language in

死磕 java同步系列之JMM(Java Memory Model)

简介 Java内存模型是在硬件内存模型上的更高层的抽象,它屏蔽了各种硬件和操作系统访问的差异性,保证了Java程序在各种平台下对内存的访问都能达到一致的效果. 硬件内存模型 在正式讲解Java的内存模型之前,我们有必要先了解一下硬件层面的一些东西. 在现代计算机的硬件体系中,CPU的运算速度是非常快的,远远高于它从存储介质读取数据的速度,这里的存储介质有很多,比如磁盘.光盘.网卡.内存等,这些存储介质有一个很明显的特点--距离CPU越近的存储介质往往越小越贵越快,距离CPU越远的存储介质往往越大

浅析java内存模型--JMM(Java Memory Model)

在并发编程中,多个线程之间采取什么机制进行通信(信息交换),什么机制进行数据的同步? 在Java语言中,采用的是共享内存模型来实现多线程之间的信息交换和数据同步的. 线程之间通过共享程序公共的状态,通过读-写内存中公共状态的方式来进行隐式的通信.同步指的是程序在控制多个线程之间执行程序的相对顺序的机制,在共享内存模型中,同步是显式的,程序员必须显式指定某个方法/代码块需要在多线程之间互斥执行. 在说Java内存模型之前,我们先说一下Java的内存结构,也就是运行时的数据区域: Java虚拟机在执