问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

C++并发:原子操作、内存模型、内存屏障

发布网友 发布时间:2024-10-05 07:34

我来回答

1个回答

热心网友 时间:2024-11-16 18:10

原子操作是指在执行过程中不会被中断的操作,要么全部执行成功,要么全部不执行,不会出现部分执行的情况。原子操作可以看作是不可分割的单元,运行期间不会有任何的上下文切换。原子操作类常用成员函数有fetch_*、store、load、exchange、compare_exchange_weak和compare_exchange_strong:

fetch_*:先获取值再计算,即返回的是修改之前的值。

store:写入数据。

load:加载并返回数据。

exchange:直接设置一个新值。

compare_exchange_weak:先比较第一个参数的值和要修改的内存值(第二个参数)是否相等,如果相等才会修改,该函数有可能在except == value时也会返回false所以一般用在while中,直到为true才退出。

compare_exchange_strong:功能和*_weak一样,不过except == value时该函数保证不会返回false,但该函数性能不如*_weak。

注意:使用操作符(如+=、++、^=等)时要看类成员是否提供对应操作符,否则可能出现意想不到的问题。

C++标准库中的原子类型,如atomic,用于实现原子操作。它提供了一种线程安全的方式来对特定类型的数据进行读取和写入,以及执行其他常见的原子操作,如增加(增量)和交换等。

内存模型描述的是程序在执行过程中内存操作正确性的问题。内存操作包括读操作和写操作,每一操作又可以用两个时间点界定:发出(Invoke)和响应(Response)。内存一致性模型描述的就是这些操作可能的执行顺序中哪些是正确的。

内存序问题:内存序(memory order)问题是由于多线程的并行执行可能导致的对共享变量的读写操作无法按照程序员预期的顺序进行。多线程运行时,可能出现指令执行级别的优化:乱序优化,流水线,乱序执行,分支预测等合理重排。因此需要内存序来*CPU对指令执行顺序的重排程度。

happens-before和synchronizes-with语义

如果两个操作之间存在依赖关系,并且一个操作一定比另一个操作先发生,那么者两个操作就存在happens-before关系;synchronizes-with关系指原子类型之间的操作,如果原子操作A在像变量X写入一个之后,接着在同一线程或其它线程原子操作B又读取该值或重新写入一个值那么A和B之间就存在synchronizes-with关系;注意这两中语义只是一种关系,并不是一种同步约束,也就是需要我们编程去保证,而不是它本身就存在

memory_order模式

C++11中引入了六种内存约束符用以解决多线程下的内存一致性问题(在头文件中),其定义如下:

Sequential consistency模型又称为顺序一致性模型,是控制粒度最严格的内存模型。在顺序一致性模型下,程序的执行顺序与代码顺序严格一致,也就是说,在顺序一致性模型中,不存在指令乱序。

Relax模型对应的是memory_order中的memory_order_relaxed。从其字面意思就能看出,其对于内存的*最小,也就是说这种方式只能「保证当前的数据访问是原子操作(不会被其他线程的操作打断)」,但是对内存访问顺序没有任何约束,也就是说对不同的数据的读写可能会被重新排序。

Acquire-Release模型的控制力度介于Relax模型和Sequential consistency模型之间。其定义如下:

假设有一个原子变量A,对其进行写操作X的时候施加了memory_order_release约束符,则在当前线程T1中,该操作X之前的任何读写操作指令都不能放在操作X之后。当另外一个线程T2对原子变量A进行读操作的时候,施加了memory_order_acquire约束符,则当前线程T1中写操作之前的任何读写操作都对线程T2可见;当另外一个线程T2对原子变量A进行读操作的时候,如果施加了memory_order_consume约束符,则当前线程T1中所有原子变量A所依赖的读写操作都对T2线程可见(没有依赖关系的内存操作就不能保证顺序)。

一个对原子变量的「load操作」时,使用memory_order_acquire约束符:在「当前线程」中,该load之后读和写操作都不能被重排到当前指令前。如果「其他线程」使用memory_order_release约束符,则对此原子变量进行store操作,在当前线程中是可见的。

假设有一个原子变量A,如果A的读操作X施加了memory_order_acquire标记,则在当前线程T1中,在操作X之后的所有读写指令都不能重排到操作X之前;当其它线程如果对A进行施加了memory_order_release约束符的写操作Y,则这个写操作Y之前所有的读写指令对当前线程T1是可见的。

一个「load操作」使用了memory_order_consume约束符:在「当前线程」中,load操作之后的依赖于此原子变量的读和写操作都不能被重排到当前指令前。如果有「其他线程」使用memory_order_release内存模型对此原子变量进行store操作,在当前线程中是可见的。

Acquire-Release模型中的其它三个约束符,要么用来约束读,要么用来约束写。那么如何对一个原子操作中的两个动作执行约束呢?这就要用到 memory_order_acq_rel,它既可以约束读,也可以约束写。

对于使用memory_order_acq_rel约束符的原子操作,对当前线程的影响就是:当前线程T1中此操作之前或者之后的内存读写都不能被重新排序(假设此操作之前的操作为操作A,此操作为操作B,此操作之后的操作为C,那么执行顺序总是ABC,这块可以理解为同一线程内的sequenced-before关系);对其它线程T2的影响是,如果T2线程使用了memory_order_release约束符的写操作,那么T2线程中写操作之前的所有操作均对T1线程可见;如果T2线程使用了memory_order_acquire约束符的读操作,则T1线程的写操作对T2线程可见。

内存屏障的引入,本质上是由于CPU重排序指令引起的。内存屏障(Memory Barrier)是一种硬件或软件指令,用于控制处理器和内存系统中对内存操作的重新排序和优化。它们的作用是确保在屏障之前和之后的内存访问按照预期的顺序进行。

内存屏障主要有两种类型:读屏障(Read Barrier)和写屏障(Write Barrier)。

读屏障(也称为加载屏障):确保在读取一个变量的值之前,所有之前的读取操作和加载操作都已经完成。这可以防止读取过期的或无效的数据。

写屏障(也称为存储屏障):确保在写入一个变量的值之前,所有之前的写入操作和存储操作都已经完成。这可以防止将新的值预先存储到缓存而不是实际写入到内存中。

内存屏障的使用可以避免在多线程或并发环境下出现的一些问题,例如数据竞争、乱序执行和原子操作的正确性。通过插入内存屏障,可以使得代码在一个屏障之前或之后的内存访问按照预期的顺序执行,从而确保正确的内存可见性和一致性。

C++中内存屏障包括:std::atomic_thread_fence、std::atomic_signal_fence、std::thread::join。

创建一个内存屏障(memory barrier),用于*内存访问的重新排序和优化。它可以保证在屏障之前的所有内存操作都在屏障完成之前完成。常见的 memory_order 参数包括:

std::memory_order_relaxed:最轻量级的内存顺序,允许重排和优化。

std::memory_order_acquire:在屏障之前的内存读操作必须在屏障完成之前完成。

std::memory_order_release:在屏障之前的内存写操作必须在屏障完成之前完成。

std::memory_order_acq_rel:同时具有 acquire 和 release 语义,适用于同时进行读写操作的屏障。

std::memory_order_seq_cst:对于读操作相当于获得,对于写操作相当于释放。
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
如何分别真金和仿金首饰 怎样区分真金和仿金首饰呢 小学生新年晚会主持人的串词!!(不要太多)急 大大后天就需要了!!!_百度... 周年晚会策划公司 奥格瑞玛传送门大厅在哪 奥格瑞玛传送门大厅怎么走 锻炼颈椎的几个动作 水多久能结冰 冰能在多长时间内形成 请问水低于0度会结冰吗? 如何防止脱发严重 嘴唇上有黑印用蜜蜡和棉线去除了胡须 上海群力草药店有治疗糖尿病的草药吗 群力草药店一定要本人去吗,膀胱癌那个医生专长,膀胱癌中晚期手术多少时... 非洲角马迁徙旅游攻略,东非旅游攻略 ...还行,但是戴眼镜后会有镜框的印记而且还有黑眼圈,像鬼啊,怎么办啊... 去肯尼亚自由行想看动物大迁徙,什么时候去比较好?求详细攻略介绍!_百度... 关于足球篮球排球 乌兹别克斯坦可以用小米华为这些吗? 表示吉祥的汉字、吉利的汉字、表示财运的汉字、有哪些?急急急急急急 东非高原动物迁徙时间是?方向是? 坦桑尼亚的塞伦盖蒂国家公园每年都有什么动物大迁徙? 降全旗是什么意思? 君威 自动版落地价最低多少钱? 东非野生动物大迁徙迁徙原因 雄霸尼注册过商标吗?还有哪些分类可以注册? 中央经济工作会议会议内容 学习中央经济工作会议精神基本信息:产品2 骆驼霸王星注册过商标吗?还有哪些分类可以注册? 手机看电影不能快进,应该要下载什么软件 苹果手机看电影快进黑屏怎么办 授渔是什么意思? 羽绒服帽子上那圈毛的作用你肯定搞错了 梦见奶嘴喝水 哪位核电仁兄给一份核电厂的地震灾害应急预案,谢谢!日本福岛事故后,我... 防震应急预案都包括哪些内容 十堰武当山风景区简介 武当山镇武当山风景区简介 黄焖鸡米饭怎样做口感更鲜美? 如何在家做出好吃的黄焖鸡米饭? 经六小纬六消防大队怎么去,从经十路上坐几路车。。谢谢,急用!_百度... 济南市高新区公安消防大队茂岭山中队地址 参加辽宁公务员考试的专业要求是什么?我学汉语言文学的,适合吗 临床医学专业本科报考辽宁省公务员可以报考哪些呢?算法学类吗?QQ:33288... 聪明糊涂心:智者的双赢处世哲学内容简介 前面四十安漏电后面一佰安能合闸吗 我想问一下,我是学机械设计制造及其自动化专业 的想问一下去太极集团... 电脑开不了机就重装系统,安装完系统自动重起时电脑黑屏就有个横杠在... 教育学考研专硕统考的满分是多少 教育学考研专硕统考的满分几分 男:生于农历1971年9月初10日早上5——7点的一生命运,不胜感激 男:生于农历1971年9月初10日早上5——7点的一生详细命运,不胜感激 ...早上4点左右出生的哪位大师帮我算下命。不胜感激!