这回该进入主题了。

        上一文最后提到了 Memory Barriers ,即内存屏障。由于对一个 CPU 而言,a = 1; b = 1. 由于在中间加了内存屏障,在 X86 架构下,就是 mfence 指令,此时在上一文中执行时。情况就变成这样了,当 CPU0 发

出 "read invalidate" 消息后,就会開始运行 mfence 指令,该指令把 Store Buffer 中的项都标记一下。然后開始运行 b = 1,此时尽管 cache hint (cache 命中),可是因为 Store Buffer 中存在被标记的项,所以

b 的新值不会直接应用到 cache 中,它也会被记录到 Store Buffer 中,并会等待被 Store Buffer 中被标记的项被应用,CPU0 也会继续运行其他指令。

        这样 CPU1 将会看到正确的 a 的值。看似完美的结局。事实上还差那么一点点。

        依旧是上一文的小样例。

a 和 b 初始化都为 0。 a 在 CPU1 的 cache 中, b 在 CPU0 的 cache 中。

        CPU 0 运行以下的代码:

        a = 1;

mfence;

        b = 1;

        CPU1 运行以下的代码:

        while (b != 1);

        assert (a == 1);

        断言一定能成功吗? 让我们如果以下的情况发生:

        1. CPU0 运行 a = 1, 可是发现 a 不在 cache 中。它就发出 "read invalidate" 消息,而且把 a 的值存在 store buffer 中;

        2。

CPU1 运行 b != 1 的比較,读取 b 的值,结果不在 cache 中,由于它不想改写,所以仅仅发一个 "read" 消息出去。

        3. CPU0 运行 mfence, 将 Store Buffer 中的项所有标记,然后运行 b = 1, 结果发现 Store Buffer 中有标记的项,所以就把 b 的值也记录在 Store Buffer,这些项是未标记的。

        4. CPU1 收到 "read invalidate" 消息,它把这个消息存入 Invalidate Queue 中。并作出回应;

        5. CPU0 收到回应,把 a 的值写入 Cache line, 把 b 的值也写入 cache line; 

        6. CPU0 收到 "read" 消息,并用出回应;

        7. CPU1 收到回应,退出循环,此时读取 a 的值,因为 Invalidate 消息还在队列中。此时它会觉得 Cache line 中 a 的值有效,但事实上为旧值,所以断言错误。

        非常明显。兵败在了 Invalidate Queue 上。那可不能够向 Store Buffer 一样。弄一个屏障在读取 Cache line 时作一下检查呢?

        假设你能想到这里,说明赶上了设计 CPU 的那些家伙。对,这里也能够用一个 mfence.

        代码就成了这个样子

        while (b != 1);

        mfence;

        assert(a == 1);

        这样当 while (b != 1) 退出循环之后,遇到了 mfence, 它就必须停下来把 Message Queue 中的所以消息应用到 Cache line 中,此时就会发现 a 的 cache line 失效。当再进行读取 a 时,就会发消息给

CPU0 。进而得到正确的结果。

事实上 X86 提供细粒度的指令 lfence (读屏障), sfence (写屏障)。 mfence(读写屏障)。

lfence: 该指令把当前invalidate queue 里的所有项标记。当 load 动作发生时,假设队列中有标记项。那么 CPU 必须把 Message Queue 中存在的消息所有应用之后,才会运行后面的指令。

这样读取就变得安全;

        sfence: 该指令把标记 Store Buffer 中所以已存在的写入记录项。当下次再有写入操作时,即使命中也不会直接应用到 cache 中。而是记录到 Store Buffer 中。

        mfence: 兼备以上两条指令的作用。

        另一些其他指令具备这种作用,一般如带 lock 前缀的指令等。

所以普通情况下内存屏障须要成对使用。

        最终快要完了。

Memory Barriers的更多相关文章

  1. 内存级别/栅栏 ( Memory Barriers / Fences ) – 翻译

    翻译自:Martin Thompson – Memory Barriers/Fences 在这篇文章里,我将讨论并发编程里最基础的技术–以内存关卡或栅栏著称.那让进程内的内存状态对其它进程可见. CP ...

  2. Synthesis of memory barriers

    A framework is provided for automatic inference of memory fences in concurrent programs. A method is ...

  3. Memory Barriers Are Like Source Control Operations

    From:   http://preshing.com/20120710/memory-barriers-are-like-source-control-operations/ If you use ...

  4. 什么是内存屏障? Why Memory Barriers ?

           要了解如何使用memory barrier,最好的方法是明白它为什么存在.CPU硬件设计为了提高指令的执行速度,增设了两个缓冲区(store buffer, invalidate que ...

  5. Memory Barriers ,cache-coherency

    http://www.rdrop.com/users/paulmck/scalability/paper/whymb.2010.07.23a.pdf Shared-Memory Synchroniza ...

  6. Linux内核同步机制之(三):memory barrier【转】

    转自:http://www.wowotech.net/kernel_synchronization/memory-barrier.html 一.前言 我记得以前上学的时候大家经常说的一个词汇叫做所见即 ...

  7. Linux内核同步 - memory barrier

    一.前言 我记得以前上学的时候大家经常说的一个词汇叫做所见即所得,有些编程工具是所见即所得的,给程序员带来极大的方便.对于一个c程序员,我们的编写的代码能所见即所得吗?我们看到的c程序的逻辑是否就是最 ...

  8. Memory Ordering in Modern Microprocessors

    Linux has supported a large number of SMP systems based on a variety of CPUs since the 2.0 kernel. L ...

  9. memory ordering 内存排序

    Memory ordering - Wikipedia https://en.wikipedia.org/wiki/Memory_ordering https://zh.wikipedia.org/w ...

随机推荐

  1. 【 学习笔记 】memcached基础知识

    源地址:http://kb.cnblogs.com/page/42731/ 仔细学习了下,以下是记录的笔记备忘内容. 一.memcached是什么?    memcached是高性能的分布式内存缓存服 ...

  2. CSS3颜色渐变模式总结

    1.线性渐变:linear-gradient 语法:= linear-gradient([ [ | to [, ]+) = [left | right] || [top | bottom] = [ | ...

  3. Redis安装-CentOs7

    官方地址 确保gcc已经安装 $ yum list installed | grep gcc $ yum install gcc 下载.提取和编辑Redis: $ wget http://downlo ...

  4. Interface与abstract类的区别

    含有abstract修饰符的class即为抽象类,abstract 类不能创建的实例对象.含有abstract方法的类必须定义为abstract class,abstract class类中的方法不必 ...

  5. AC日记——[Noi2011]阿狸的打字机 bzoj 2434

    2434 思路: 构建ac自动机: 抽离fail树: 根据字符串建立主席树: 在线处理询问: 询问x在y中出现多少次,等同于y有多少字母的fail能走到x: 1a,hahahahah: 代码: #in ...

  6. Rescue The Princess

    Description Several days ago, a beast caught a beautiful princess and the princess was put in prison ...

  7. scrapy xpath 从response中获取li,然后再获取li中img的src

    lis = response.xpath("//ul/li") for li in lis: src = li.xpath("img/@src") # 如果xp ...

  8. notepad++ 删除重复记录

    sort line with Edit -> Line Operations -> Sort Lines Lexicographically ascending do a Find / R ...

  9. 理解XML-RPC

    有关XML-RPC http://baike.baidu.com/link?url=ejidFtjelUzPv75VBm5_XrzSbHtFgArYY47S1s1NK2_m-auOr10sTeRh6U ...

  10. FFT&NTT&多项式相关

    打了FFT 感觉以后多项式不虚了 ~滑稽~ PS 关于详见没写完.... code #include<cmath> #include<cstdio> #include<c ...