zoukankan      html  css  js  c++  java
  • "Loads are not reorderd with other loads" is a FACT!!

    对于多线程编程的难度,再充分的心里准备也许都是不够的。前一段时间一直在整理一些有关多线程编程的内容(一个对多线程算法库编写过程中的经验积累)。而在前天,一篇来自于Microsoft PFXJoe的博文惊现:"Loads cannot pass other loads" is a ~myth,着实让人惊出了一身冷汗。

     

    讨论集中在了以下的例子上:

     

        P0          P1
        ==========  ==========
        X = 1;      Y = 1;
        R0 = X;     R2 = Y;
        R1 = Y;     R3 = X;

     

    问:如果X, Y volatile 有没有可能使得执行完毕之后 R1 == R3 == 0 呢?

     

    先不说结果,从现象分析,具体信息请参考。首先,在.NET 的内存模型下,任何store均有relase语义而任何volatileload均有acquire语义。由于相关,R0 = X 不可能调整到 X = 1 之前执行;同理 R2 = Y 也不可能调整到 Y = 1 执行。参考Intel 白皮书中的2.1节可知,“loads are not reordered with other loads and stores are not reorderd with other stores”。因此 R1=Y也不可能移动到R0=X之前,同理,R3=X也不能移动到R2=Y之前。

     

    综上所述,想要得到R1==R3==0的结果看上去是不可能的。但是这个事情确实有可能发生。参考Intel的白皮书中的2.4节:“intra-processor forwarding is allowed”恰恰举了相同的例子,并且指出,R1==R3==0是完全可能的。Joe指出,在这种情况下,程序就好像是这样运作的:

        P0          P1
        ==========  ==========
        R1 = Y;     R3 = X;
        X = 1;      Y = 1;
        R0 = X;     R2 = Y;

     

    这是怎么一回事呢,难道自相矛盾吗?实际上不是的!白皮书中2.1节说明的情况是memory reorder,而2.4节并没有否定2.1的内容。内存访问的reorder规则仅仅满足于当前的processor,而并不保证所有的结果其余的processor可见。这是由于写入延迟造成的。因此这个问题并没有否定在上述例子中reorder不可能发生的事实,而是对于其他处理器来说“好像是”发生了reorder一样。

     

    load acquire与store release实际上看做不完整的half fence,不能保证其他CPU的可见性。那么这种问题如何解决呢?参考Intel 64 And IA-32 Programming Manual可知,如果要保证可见性,应该在必要的位置使用memory fence。因此,解决上述问题的方式是在恰当的地方添加full fence,或者包含隐式full fence的指令,例如Interlocked.Xxx。即

        P0          P1
        ==========  ==========
        X = 1;      Y = 1;

        MemoryFence;MemoryFence;
        R0 = X;     R2 = Y;
        R1 = Y;     R3 = X;

     

    注:在.NET framework中,插入一个Full fence可以使用 System.Threading.Thread.MemoryBarrier()方法。

     

  • 相关阅读:
    执行git log/status等命令时,重新打开了个窗口,必须按q才能退出
    ./configure时候遇到的问题 Cannot find install-sh, install.sh, or shtool in ac-aux
    Linux tty驱动架构
    of_property_read_string_index(转)
    Linux 内核启动信息的打印 --- dev_driver_string函数/dev_name函数
    USB、UART、SPI等总线速率(转)
    在业务中的逻辑思维
    在无法判断是否会出错的情况下进行的操作
    jqgrid 不能选中行, 每次点击单元格都会选中最后一行(也有可能是其他行)
    H+关闭tab框
  • 原文地址:https://www.cnblogs.com/lxconan/p/1246569.html
Copyright © 2011-2022 走看看