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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Selenimu Chrome驱动下载地址「建议收藏」

    Selenimu Chrome驱动下载地址「建议收藏」S

    2022年6月23日
    33
  • 趣味编程游戏_全脑开发训练100个游戏

    趣味编程游戏_全脑开发训练100个游戏在信息技术迅猛发展的时代,操纵计算机,与电脑对话的能力已经成了事实上的技能标配,也已经深深地融入了我们每个人的生活当中。游戏行业也不例外,近几年,随着全民编程的热潮,许多游戏厂商也纷纷把编程融入自己的游戏当中,甚至推出了许多专门为编程爱好者/编程学习者制作的编程解密游戏。今天要推荐的九个游戏,可谓风格各异,老少咸宜,不论你是对编程完全陌生的新手,还是硬核老鸟,一定能找到一款适合你的游戏。话…

    2022年4月19日
    97
  • java语言和C语言的区别

    java语言和C语言的区别简单的说就是两种不同的语言.但是它们之间既有联系又有区别

    2022年7月8日
    23
  • 选用TypeScript开发AngularJS2[通俗易懂]

    选用TypeScript开发AngularJS2

    2022年3月4日
    41
  • 如何将深度学习的float32图像转为Unit8格式以方便cv2使用

    如何将深度学习的float32图像转为Unit8格式以方便cv2使用在使用Pyside2中的QImage处理深度学习模型生成的图片时,需要将float32的图像转为Unit8格式,再使用cv2处理。一开始使用网上的其他教程,如下: #模型生成 G_recon=G(self.content,True) #将(1,3,256,256)尺寸的转为(256,256,3)G_recon=((G_recon[0].cpu().detach().numpy().transpose(1,2,0)+1)/2)

    2022年9月15日
    2
  • 数据采集技术python网络爬虫_精通Python网络爬虫

    数据采集技术python网络爬虫_精通Python网络爬虫Python网络爬虫与数据采集第1章序章网络爬虫基础1爬虫基本概述1.1爬虫是什么1.2爬虫可以做什么1.3爬虫的分类1.4爬虫的基本流程1.4.1浏览网页的流程1.4.2爬虫的基本流程1.5爬虫与反爬虫1.5.1爬虫的攻与防1.5.2常见的反爬与反反爬1.6爬虫的合法性与robots协议1.6.1robots协议1.6.2查看网页的robots协议1.7Python爬虫相关库2.Chrome浏览器开发者工具2.1Chrome浏览器开发者工具简述2.1

    2022年9月1日
    2

发表回复

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

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