MemoryBarrier[通俗易懂]

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

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

查了下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://javaforall.net/157894.html原文链接:https://javaforall.net

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


相关推荐

  • Ubuntu 18.04 浏览器安装flash[通俗易懂]

    flash官网(注意下载和系统浏览器相对应的包)PPAPI:供Opera(15以上)、Chromium(开源谷歌)浏览器使用NPAPI:适用于FireFox(火狐)、Safari(苹果)、Opera(欧朋,12.17版以下)然后解压:tar-zxvfflash_player_npapi_linux.x86_64.tar.gz复制:sudocplibflashplay…

    2022年4月12日
    64
  • jasypt加密配置文件_jenkins api

    jasypt加密配置文件_jenkins apiJasypt加密框架概述1、JasyptSpringBoot为springboot应用程序中的属性源提供加密支持,出于安全考虑,Springboot配置文件中的敏感信息通常需要对它进行加密/脱敏处理,尽量不使用明文,要实现这一点,办法有很多,自己手动对敏感信息进行加解密也是可以的。2、有需求就有人奉献,Jasypt开源安全框架就是专门用于处理Springboot属性加密的,在配置文件中直接配置密文,然后应用启动的时候,Jasypt会自动将密码解密成明文供程序使用。3、

    2022年9月26日
    0
  • 异步fifo设计注意事项有哪些(陈设设计)

    近日学习用到异步FIFO,故写下这篇博客记录学习心得。在我看来,异步FIFO的设计注意事项大体分为两点:亚稳态的处理空满状态的判断第一,来说一下亚稳态。亚稳态是指触发器无法在某个规定时间内达到一个可确认的状态。在FIFO的设计中,产生的原因主要由两点:一是逻辑电平的误判,也就是如果通过二进制作为指针来判断空满状态,因二进制数值变化引起的位数变化大,对电路的危害也随之增加,故在本设计中使…

    2022年4月15日
    56
  • MBus协议详解(三)[通俗易懂]

    MBus协议详解(三)[通俗易懂]这节主要集中在MBus协议物理层和数据链路层的硬件实现上,其关键点包括:1、由主到从传输的时候电压的调制;2、由从到主传输的时候电流脉冲的调制;3、总线短路保护。1、由主到从传输的时候电压的调制如上图所示,信号在-27V、0V、+15V上进行调制,采用2个MOS管P201、P202,+15V电压通过稳压器降压到+12V。由主到从传输数据的时…

    2022年10月15日
    0
  • 原则与执着:暴雪王牌总结游戏研发得失成败「建议收藏」

    原则与执着:暴雪王牌总结游戏研发得失成败「建议收藏」暴雪执行副总裁、diablo3设计师RobPardo在本年度GDC上详细讲述了暴雪在游戏设计理念的主要原则,总结暴雪过去十余年中的经验教训。  RobPardo在暴雪长期负责游戏设计方面的工作,具有极其丰富的成功经验。他曾是《星际争霸》、《星际争霸:母巢之战》、《魔兽争霸3:混乱之治》、《魔兽争霸3:冰封王座》、《魔兽世界》、《魔兽世界:燃烧远征》的主要设计者,2006年他以《魔兽世界》

    2022年5月7日
    75
  • 第四章:java 多线程volatile关键字 atomic类学习 java 原子性讲解,变量可见与不可见说明

    第四章:java 多线程volatile关键字 atomic类学习 java 原子性讲解,变量可见与不可见说明第四章:java 多线程volatile关键字 atomic类学习 java 原子性讲解,变量可见与不可见说明

    2022年4月23日
    40

发表回复

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

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