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


相关推荐

  • C语言程序设计第五版 谭浩强 第五版课后答案

    C语言程序设计第五版 谭浩强 第五版课后答案谭浩强C语言程序设计第五版第4章课后答案3.求两个正整数m和n,求其最大公约数和最小公倍数。#include<stdio.h>voidmain(){ intm,n,t,i,a=1; scanf(“%d%d”,&m,&n); if(m<n) { t=m; m=n; n=t; } for(i…

    2022年6月14日
    44
  • Qt quick性能提升[通俗易懂]

    Qt quick性能提升[通俗易懂]Qtquick性能优化使用时间驱动  避免定时轮询;  使用信号槽形式;使用多线程  C++;  QMLWorkerScript元件;使用QtQuickCompiler  只需要再PRO文件中添加一行:CONIFG+=qtquickcompiler避免使用CPU渲染的元件;  Canvas、QtCharts;使用异步加载  图片异步加载…

    2026年2月1日
    2
  • 在给elasticsearch安装head插件时,npm install 版本不匹配[通俗易懂]

    在给elasticsearch安装head插件时,npm install 版本不匹配

    2022年2月20日
    45
  • 最小二乘法的矩阵推导

    最小二乘法的矩阵推导顾名思义,从数学意义推导最小二乘法公式:一,解释最小二乘法本质是寻找一组x,使Ax与b距离最近。写成二范数的形式为:最合适的x一般出现在函数的极值点,也就是导数为0的点,所以为求导计算方便,我们用二范数的平方作为计算公式:补充知识:(1)二范数二,推导补充知识:设下列向量条件(2)标量对列向量求导证明过程:另一个同理可证。(3)特殊标量对列向量求…

    2022年5月13日
    58
  • iOS逆向入门实践 — 逆向微信,伪装定位(二)

    iOS逆向入门实践 — 逆向微信,伪装定位(二)1.创建工程还是跟之前的步骤一致,创建工程,然后配置Makefile。注意创建工程时名字只能包含数字跟字母。Makefile上面引入的 FakeWeChatLocationManager.m 文件是主要代码实现的地方,分离出来好模块化。2.Reveal注入为了更好地定位代码,需要分析一下“附近的人”这个界面对应的类名是什么,然后进一步分析

    2022年6月2日
    43
  • 基本全局阈值法(basic global thresholding)MATLAB实现

    基本全局阈值法(basic global thresholding)MATLAB实现基本全局阈值分割步骤如下:(1)设定参数,并选择一个初始的估计阈值。(2)用阈值分割图像。将图像分成两部分:是由灰度值大于的像素组成,是由灰度值小于或等于的像素组成。(3)计算和中所有像素的平均灰度值和,以及新的阈值。(4)如果,则推出即为最优阈值;否则,将赋值给,并重复步骤(2)~(4),直到获取最优阈值。其具体实现MATLAB代码如下:%i…

    2022年5月24日
    35

发表回复

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

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