发信人: yifanw (王轶凡), 信区: CPlusPlus
标  题: 内存模型之白话解决方案
发信站: 水木社区 (Sun Mar 15 17:02:31 2009), 站内

99%的情况下:

大多数程序员在写多线程程序的时候,都是使用os或是thread library提供的同步原语
(semaphore、lock/spinlock、monitor等)把共享变量包围起来。这些同步原语都保证对
共享变量的读写会在临界区内完成,不会乱序到lock之前,也不会乱序到unlock之后。所以
99%的程序员是不需要的关心memory ordering的,只要全部且正确的使用了各种锁,基本上
就可以写出线程安全的程序。

上一篇白话入门中,double checked locking就是属于不想在quick-path上使用锁,做
了一个不成熟的优化,而引入了bug。

1%的情况下:

由于种种原因,你不想使用lock来做同步,这就需要了解memory ordering,并采用如
下解决方案:

(A) 山寨解决方案:

(1)阻止编译器的优化
    针对编译器的优化,可以使用volatile来修饰相应的share variable,编译器*应该*不
会reorder那些volatile variable的read & write,也不会把它们装到register中。但是,
volatile的语义是各个compiler自己决定的,所以在使用之前,最好详细了解。
Visual C++ 2005中volatile的功能很强,文挡也很清楚:
http://msdn2.microsoft.com/en-us/library/12a04hfd.aspx;
我没有能找到gcc关于volatile的详细文档。

(2)阻止CPU的优化
     Intel提供了一些指令,来解决CPU的memory ordering的问题:
lfence:一个针对load的fence,在lfence之前所有的load(按照program order)都会在
lfence之前执行;在lfence之后的所有load(按照program order)都会在lfence之后执行

sfence:一个针对store的fence,在sfence之前所有的store(按照program order)都会在
sfence之前执行;在sfence之后所有的store(按照program order)都会在sfence之后执行

mfence:等同于lfence + sfence,在mfence之前所有的load & store(按照program
order)都会在mfence之前执行;在mfence之后所有的load & store(按照program order)
都会在mfence之后执行。

此外,带lock prefix的instruction都相当于执行了一个mfence。

(B) 完全解决方案:

山寨解决方案不是很完美,需要程序员了解CPU、汇编和编译器优化,而且程序移植到
其他系统上也会有一些麻烦。各个语言社区都在想办法把这个底层细节抽象出来,使得程序
员用一个很简单优雅的方式就能指定需要memory ordering,把实现细节留给编译器。

于是,有了两个术语:
    (1) acquire语义: 如果操作A拥有acquire语义,A后面的所有的load, store都不会乱
序到A之前
    (2) release语义: 如果操作C拥有release语义,C前面的所有的load, store都不会乱
序到C之后

就是说acquire操作是一个向后的barrier,没有东西可以跑到它前面去;release操作是一
个向前的barrier,没有东西可以到它后面去。

|======> acquire       release <=======|

在Java/C#/VC2005中,对一个volatile variable的read和对各种lock的加锁拥有acquire语
义;对一个volatile variable的write和对各种lock的解锁拥有release语义。

在C++ 0x中,对volatile没有相应的规定,但是对atomic variable(使用atomic library)
的读写和对锁的加解锁也都有类似的acquire/release语义。

这里也解释了为什么使用锁之类的东西,基本不会受到memory ordering的困扰:共享变量
的write/read是不会乱序到临界区之外的,而我们只在临界区内读写共享变量。

只要我们使用acquire/release来指明程序需要的memory ordering,就可以不关心编译器的
优化、CPU的乱序(编译器会做掉剩下的时候,比如压制优化,生成指令来阻止CPU乱序)。

下面来看一个非常简单的C#的例子:

using System;
using System.Threading;
class Test {
    public static int result;
    public static volatile bool finished;

static void Thread2() {
        result = 143;
        finished = true;
    }

static void Main() {
        finished = false;

new Thread(new ThreadStart(Thread2)).Start();

for (;;) {
            if (finished) {
                Console.WriteLine("result = {0}", result);
                return;
            }
        }
    }
}

finished被用来作为thread2退出的标志,需要被两个thread共享,所以我们把它做成
volatile,来防止编译器优化(把它装在register中)和CPU乱序(防止Thread2()中
finished先于result被赋值,或者Main中result先于finished被读取)。

但是result同样是一个共享变量,为什么不需要做成volatile呢?因为没有这个必要,首先
考虑Thread2()中对finished的赋值,这是一个volatile write,拥有release语义,这可以
保证对result的赋值必然先完成;Main中对finished的读取是一个volatile read,拥有
acquire语义,这可以保证对result的读取必然后完成。所以,result是不需要做成
volatile的。

--
欢迎来CSARCH版

※ 修改:·yifanw 于 Mar 15 17:29:55 2009 修改本文·[FROM:222.67.1.*]                                                   
※ 来源:·水木社区 newsmth.net·[FROM:222.67.1.*]

转载于:https://www.cnblogs.com/shawn-zhou/archive/2009/03/16/1413574.html

[zz from newsmth]王大牛的Memory Model白话系列(2)相关推荐

  1. [zz from newsmth]王大牛的Memory Model白话系列(1)

    发信人: yifanw (王轶凡), 信区: CPlusPlus 标  题: 内存模型之白话入门 发信站: 水木社区 (Sun Mar 15 12:49:50 2009), 站内 程序员眼中的多处理器 ...

  2. [zz from newsmth] 王大牛的Memory Model reading list

    发信人: yifanw (王轶凡), 信区: CPlusPlus 标  题: 内存模型之参考文献 发信站: 水木社区 (Sun Mar 15 22:51:46 2009), 站内 前两篇文章,希望大家 ...

  3. Java内存模型(Java Memory Model,JMM)

    导读 本文通过对JSR133规范的解读,详细的介绍JMM的核心理论,并将开发中常用的关键字的实现原来做了详细的介绍.通过本文读者可以了解到并发的一些基本理论,并对一些同步原语有了更深层次的理解.希望读 ...

  4. Java (JVM) Memory Model – Memory Management in Java

    原文地址:http://www.journaldev.com/2856/java-jvm-memory-model-memory-management-in-java Understanding JV ...

  5. JAVA 内存模型 (Java Memory Model,JMM)

    JAVA内存模型 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转到教程. Java内存模型(Java Memory Model,JMM) 是在硬件内存模型基 ...

  6. 浅谈Opencl四大模型之Memory Model

    运行模型(execution model)讲述了一个kernel怎么样在opencl平台运行,host喝kernel如何交互的,kernel代码如何编译的等等,但是没有涉及到opencl内存的管理方式 ...

  7. 稀疏内存模型sparsemem memory model | 文章

    文章推荐 <sparsemem memory model>https://lwn.net/Articles/134804/ <Physical Memory Model>htt ...

  8. JSR-133: JavaTM Memory Model and Thread Specification原文解析

    http://www.cs.umd.edu/~pugh/java/memoryModel/ http://www.cs.umd.edu/~pugh/java/memoryModel/jsr133.pd ...

  9. N76E003开发中Keil memory model设置

    上一篇中说,选择Xdata就可以用了.今天改程序,发现编译是没有错了,可是下载进去总是复位.排查复位标志是,硬件故障引起的复位.HardF 硬件故障标志.最后排查下拉,还是这个memory model ...

最新文章

  1. 程序员四大忌 你该如何避免呢?
  2. 鼠标移到某一行 某一行变色 鼠标移开恢复
  3. pywinauto简单示例
  4. [2018.07.26 T2] 背包问题
  5. 惠普HP Laser 108a 打印机驱动
  6. 标题中冒号的用法_英文中冒号的各种用法
  7. Mac有些网址打不开问题解决办法
  8. MATLAB bp神经网络的雾霾天气下交通标志的识别系统
  9. 富士通南大实习五月记
  10. 左连接(LEFT JOIN)实例
  11. 如何治理VOCs有机废气的方法——吸附
  12. Visual Studio Ultimate 2013 下载地址+序列号
  13. 小学计算机课程目录五年级,小学五年级信息技术课件
  14. 测试成长小说5 这个锅我不背
  15. nfs 客户端卡死问题
  16. python与图论的桥梁——igraph
  17. 微信iPad协议,个人号API开发
  18. html语言中可视化标签,eyoucms uihtml 带html富文本可视化标签
  19. 1024 - 在这里起航!
  20. 请教ASP.NET培训应该培训的内容和以及顺序

热门文章

  1. 话说软件结构设计的图形工具
  2. 开源SCADA组态软件Qt,C#,和WEB大全
  3. 2022年中职组网络安全国赛A模块解析第二套
  4. android studio 读音,simplicity
  5. 借助RESTful API,用Excel开发网站,可用于多人在线实时编辑Excel,有实例下载
  6. 中国的程序员与日本程序员
  7. 从商品溯源到历史载录,区块链技术的革新
  8. skip-gram模型理解
  9. 2016服务器系统稳定吗,Windows Server 2016最受企业欢迎的5大特性
  10. 三分钟读懂外汇保证金交易,告诉你我为什么要做外汇交易!(开篇)