他多爱你几分,你多还他几分,找幸福的可能。
内存屏障也称内存栅栏内存栅障屏障指令等 是一类同步屏障指令是CPU或编译器在对内存随机访问的操作中的一个同步点使得此点之前的所有读写操作都执行后才可以开始执行此点之后的操作
大多数现代计算机为了提高性能而采取乱序执行这使得内存屏障成为必须
语义上内存屏障之前的所有写操作都要写入内存内存屏障之后的读操作都可以获得同步屏障之前的写操作的结果因此对于敏感的程序块写操作之后读操作之前可以插入内存屏障
1.编译器引起的内存屏障
2.缓存引起的内存屏障
3.乱序执行引起的内存屏障
我们都知道从寄存器里面取一个数要比从内存中取快的多所以有时候编译器为了编译出优化度更高的程序就会把一些常用变量放到寄存器中下次使用该变量的时候就直接从寄存器中取而不再访问内存这就出现了问题当其他线程把内存中的值改变了怎么办也许你会想编译器怎么会那么笨犯这种低级错误呢是的编译器没你想象的那么聪明让我们看下面的代码(代码摘自《独辟蹊径品内核》)
int flag=0;51, 51, 51; text-indent: 2em;">void wait(){51, 51, 51; text-indent: 2em;">while ( flag == 0 )51, 51, 51; text-indent: 2em;">sleep(1000);51, 51, 51; text-indent: 2em;">51, 51, 51; text-indent: 2em;">}51, 51, 51; text-indent: 2em;">void wakeup(){51, 51, 51; text-indent: 2em;">flag=1;51, 51, 51; text-indent: 2em;">}
这段代码表示一个线程在循环等待另一个线程修改flag Gcc等编译器在编译的时候发现sleep()不会修改flag的值所以为了提高效率它就会把某个寄存器分配给flag于是编译后就生成了这样的伪汇编代码51, 51, 51; text-indent: 2em;">void wait(){51, 51, 51; text-indent: 2em;">movl flag %eax;51, 51, 51; text-indent: 2em;">while ( %eax == 0)51, 51, 51; text-indent: 2em;">sleep(1000);51, 51, 51; text-indent: 2em;">}
这时当wakeup函数修改了flag的值wait函数还在傻乎乎的读寄存器的值而不知道其实flag已经改变了线程就会死循环下去由此可见编译器的优化带来了相反的效果
但是你又不能说是让编译器放弃这种优化因为在很多场合下这种优化带来的性能是十分可观的那我们该怎么办呢有没有什么办法可以避免这种情况答案必须是肯定的我们可以使用关键字volaTIle来避免这种情况
volaTIle int flag = 0;
这样我们就能避免编译器把某个寄存器分配给flag了
好上面所描述这些就叫做编译器优化引起的内存屏障是不是懂了点什么再回去看看概念
好既然寄存器能够引起这样的问题那么缓存呢我们都知道CPU会把数据取到一个叫做cache的地方然后下次取的时候直接访问cache写入的时候也先将值写入cache
那么先让我们考虑在单核的情况下会不会出现问题呢先想一下单核情况下除了CPU还会有什么会修改内存对了是外部设备的DMA那么DMA修改内存会不会引起内存屏障的问题呢答案是在现在的体系结构中不会
当外部设备的DMA操作结束的时候会有一种机制保证CPU知道他对应的缓存行已经失效了而当CPU发动DMA操作时在想外部设备发送启动命令前需要把对应cache中的内容写回内存在大多数RISC的架构中这种机制是通过一写个特殊指令来实现的在X86上采用一种叫做总线监测技术的方法来实现就是CPU和外部设备访问内存的时候都需要经过总线的仲裁有一个专门的硬件模块用于记录cache中的内存区域当外部设备对内存写入的时候就通过这个硬件来判断下改内存区域是否在cache中然后再进行相应的操作
那么什么时候才能产生cache引起的内存屏障呢多CPU 是的在多CPU的系统里面每个CPU都有自己的cache当同一个内存区域同时存在于两个CPU的cache中时CPU1改变了自己cache中的值但是CPU2却仍然在自己的cache中读取那个旧值这种结果是不是很杯具呢因为没有访存操作总线也是没有办法监测的这时候怎么办
对阿怎么办呢我们需要在CPU2读取操作之前使自己的cache失效x86下很多指令能做到这点如lock前缀的指令cpuid iret等内核中使用了一些函数来完成这个功能mb() rmb() wmb()用的也是以上那些指令感兴趣可以去看下内核代码
我们都知道超标量处理器越来越流行连龙芯都是四发射的超标量实际上就是一个CPU拥有多条独立的流水线一次可以发射多条指令因此很多允许指令的乱序执行具体怎么个乱序方法可以去看体系结构方面的书这里只说内存屏障
指令乱序执行了就会出现问题假设指令1给某个内存赋值指令2从该内存取值用来运算如果他们两个颠倒了指令2先从内存中取值运算是不是就错了
对于这种情况x86上专门提供了lfencesfence和mfence 指令来停止流水线
lfence停止相关流水线知道lfence之前对内存进行的读取操作指令全部完成
sfence停止相关流水线知道lfence之前对内存进行的写入操作指令全部完成
mfence停止相关流水线知道lfence之前对内存进行的读写操作指令全部完成
如果不想电脑太卡的话c盘不要放太多东西,否则电脑c盘空间很容易不足的,最好把下载的东西放到电脑d盘。那么已经放到c盘的东西怎么移到d盘呢?下面一起来看看吧!电脑c盘怎么移到d盘在电脑里如何把默认C盘位置改到d盘,接下来给大家分享具体操作方法,需要的朋友可以参考下。1、首先在电脑上……阅读全文 >>
随着科学技术的不断发展,电脑已经得到了很大程度上的普及,现在几乎每家每户都拥有自己的一台电脑,那么大家对电脑了解吗?知道电脑有哪些重要的组成部分,电脑的重要组成部分包括主板、CUP显卡、内存条等,那么今天小编就给大家介绍一下内存吧,大家知道内存的重要性吗?它在电脑的整个运行过程中……阅读全文 >>
华为正式发布了新机华为畅享8系列手机,很多人都想要入手。华为畅享8内存多大呢?这也是很多网友们比较关注的问题,毕竟手机内存大小影响到后期的使用效果。接下来详细为大家介绍这款华为畅享8:华为畅享8内存多大?华为畅享8提供金色、蓝色、黑色、粉色4款颜色,拥有3GB内存+32GB存储、……阅读全文 >>
联想笔记本使电脑快速释放内存,调整注册表可解决此问题,具体步骤如下:1、按“win+r”在运行栏中输入“regedit”进入注册表。2、依次打开注册表至“HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersio……阅读全文 >>
在电脑硬件中,显卡,内存,处理器等都在电脑主机扮演着重要角色,因此如果当中一个硬件出现,就会导致电脑运行不正常,如果电脑内存坏了,电脑主机会有什么问题?1.开机黑屏,主板报警。如果是开机黑屏,主板发出嘟嘟嘟的叫声,那还是比较好办的。你只需要打开电脑主机,重新插拔下内存条即可。但是……阅读全文 >>
内存就是暂时存储程序以及数据的地方,比如当我们在使用WPS处理文稿时,当你在键盘上敲入字符时,它就被存入内存中,当你选择存盘时,内存中的数据才会被存入硬(磁)盘。下面,我们就来看看如何降低内存使用率。1、首先,我们怎么来判断内存使用率过高?根据一些软件的评判标准来看,一个是看CP……阅读全文 >>
很多购买电脑的同学仍然还不清楚内存和硬盘到底有什么区别,在电脑里面有什么作用,容易把内存当硬盘或把硬盘当内存,下面小编通俗易懂的来给大家讲讲硬盘跟内存有和区别,在电脑中分别扮演的是什么角色。硬盘与内存区别说到内存,很多人容易将电脑里面的内存条跟内存卡之类的混淆,其实,电脑里面的内……阅读全文 >>
内存盘是什么?内存盘是一种虚拟的电脑软件,主要是用于对电脑的数据进行保存的,可以充当电脑的硬盘进行使用。内存盘也被称为虚拟内存盘,它是一种可以提高电脑内存和文件快速访问的技术。但是内存盘会导致电脑在关闭之后会出现数据丢失,内存盘是比较不安全是一种设置。那么下面,小编来告诉大家内存……阅读全文 >>
我们都知道当精子和卵子结合后,才能孕育出一个生命,而精子是比较直观能看到的,卵子就很少有人了解,在女性排卵期间,成熟的卵泡会排出卵子,但是卵子在女性的体内也是有存活时间的,那么女性排卵后卵泡在体内存活多久呢?女性排卵后卵泡在体内存活多久?健康的女性每个月都会排卵,强壮有活力的精子……阅读全文 >>
小米红米手机3的内存容量是多少小米红米手机3的内存容量是16GB。根据提供的消息资料,就能了解到小米红米手机3的内存容量是多少。小米红米手机3采用金属机身,其背面由4166颗星星成菱形排列,设计灵感来自夜空中的繁星。当光线游走在圆点间,繁星被依次点亮,用户能感受到视觉上的丰富变化……阅读全文 >>