MemoryBarrier方法[通俗易懂]

MemoryBarrier方法[通俗易懂]查了下MSDN的解释:MemoryBarrierisrequiredonlyonmultiprocessorsystemswithweakmemoryordering(forexample,asystememployingmultipleIntelItaniumprocessors).Syn…

大家好,又见面了,我是你们的朋友全栈君。

查了下MSDN的解释:

             MemoryBarrier is required only on multiprocessor systems with weak memory ordering (for example, a system employing multiple Intel Itanium processors).

             Synchronizes memory access as follows: The processor executing the current thread cannot reorder instructions in such a way that memory accesses prior to the call to MemoryBarrier execute after memory accesses that follow the call to MemoryBarrier.

            就是说多核处理器会对运行CPU指令顺序重排优化,MemoryBarrier可以阻止指令重排,调用Thread.MemoryBarrier()之后的代码中内存访问不能再这之前就完成了。也就是它可以限制指令重排和内存读写的缓存。

         下面有段代码,在release编译情况下会死循环(debug应该是没做instructions reorder而不会有问题)

            bool complete = false;
            var t = new Thread(() =>
            {
   
   
                bool toggle = false;
                while (!complete)
                    toggle = !toggle;
            });
            t.Start();
            Thread.Sleep(1000);
            complete = true;
            t.Join();

问题原因:

1.编译器、CLR或者CPU可能重新排序了程序指令,以此提高效率。

2.编译器、CLR或者CPU引入缓存优化导致其他的线程不能马上看到变量值的更改。

 

尝试了下将Thread.MomoryBarrier加到while中,保证complete读到的最新的:

此例子中MomoryBarrier 应该时解决jit时过度优化,虽然两个核心cache line 不会及时同步,complete 值修改通过MSIE协议也很快的通知到其他核心。

出现死循环在于jit 任魏complete值一直是false,并没有执行load操作,而是直接判断true跳转。

            bool complete = false;
            var t = new Thread(() =>
            {
   
   
                bool toggle = false;
                while (!complete)
                {
   
   
                   Thread.MemoryBarrier();
                    toggle = !toggle;
                }
            });
            t.Start();
            Thread.Sleep(1000);
            complete = true;
            t.Join();

在看一个例子:(来自《window 并发编程指南》内存模型部分)
MyObject mo= ..;
int f= mo.field;
if(f==0)
{
  //same operation
  Console.WriteLine(f);
}
如果mo.field 在读取和Console.WriteLine相隔足够远,那么编译器可能会认为读mo.field 读取两遍会更有效,被编译成如下代码:
MyObject mo= ..;
if(mo.filed==0)
{
  //same operation
  Console.WriteLine(mo.field);
}
编译器可能判断,保留这个值是否给寄存器带来压力并导致栈空间的低效使用,并且之个分支是否很少被使用(因此f值就不需要多次)
这样带来多线程问题,将f值使用volatitle修饰,可禁止这种优化


转载于:https://www.cnblogs.com/lulu/archive/2012/05/26/2519580.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/157901.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • ESLint-的基本介绍[通俗易懂]

    ESLint-的基本介绍[通俗易懂]什么是eslintESLint是一个代码检查工具,用来检查你的代码是否符合指定的规范(例如:=的前后必须有一个空格)。规范行业推荐的规范;在创建项目时,我们使用的是JavaScriptStandardStyle代码风格的规则自定义的规范。你和你的团队可以自行约定一套规范使用ESLint的好处在于:多人协作时代码风格统一eslint是法官,Standard是法律vue-cli工具在创建项目时提供选项,我们前面在创建项目时选中了它,所以它在本项目中是直接生效

    2022年6月18日
  • setproperty java_Java中System.setProperty()的用法

    setproperty java_Java中System.setProperty()的用法该方法的作用是:设置指定键指示的系统属性在实际项目中发现,如果一个服务器下放置了多个web项目的话,在一个项目中通过调用System.setProperty设置了某个值,再另一个项目中也能获取到该值,所以如果想在一个项目中设置全局变量时尽量避免使用这个方法,应该调用相应的appContext。/**设置指定键对值的系统属性*setProperty(Stringprop,Stringva…

    2022年7月12日
  • JMeter下载安装以及使用教程

    JMeter下载安装以及使用教程JMeter下载1、下载地址:https://jmeter.apache.org/download_jmeter.cgi2、下载后无需安装,解压后即可使用。解压后目录如下:3、打开JMeter中bin目录下面的jmeter.bat双击即可打开JMeter了,打开的时候会有两个窗口,Jmeter的命令窗口和Jmeter的图形操作界面,不要关闭命令窗口,打开界面如下:4、打开jmeter软件,发现显示的为英文,更改为中文步骤如下:点击菜单栏【Options】按钮然后依次单击【Cho

    2022年10月31日
  • 计算机二级选择题——数据结构与算法[通俗易懂]

    计算机二级选择题——数据结构与算法[通俗易懂]按照自己的理解写的解题思路,如有错误希望指正。1.算法的复杂度: ①时间复杂度:执行算法所需的计算工作量(又叫:基本运算次数) ②空间复杂度:执行算法所需的内存 它们是没有任何关系的!!!2.求二叉树序列类题目 要点:前序—根左右 中序—左根右 后序—左右根 例1:已知前序ABCDE,中序BCADE,求后序;同类型,已知任意两个求第三个 解题思路: 由前序知道A是根,结合中序,CB是左子树,DE…

    2022年8月18日
  • 解压war包工具_rar解压下载

    解压war包工具_rar解压下载解压war,要用jar命令jar-xfdemo.war

    2022年10月5日
  • 断开和服务器共享连接的方法「建议收藏」

    断开和服务器共享连接的方法「建议收藏」断开和服务器共享连接的方法

    2022年4月25日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号