zoukankan      html  css  js  c++  java
  • 关于.net中线程原子性的自我总结

    首先来张图,一张 cpu的简图,仅从个人理解角度理解画的

     

      大体 解释下这张图 这是 一张 i5的简图i5 大家都知道 是双核四线程,(超线程技术)l1,l2,l3是 1,2,3级缓存。

      Cpu工作:每次计算任务 cpu 都去找l1,如果l1没有就去找l2,依次查找,然后依次将数据从内存加载l3,l2,l1 然后加载到 寄存器操作。

      现在引入 一个问题 a+=1; 怎么执行的

      首先 a+=1 是 分成 以下几部执行的

    1. 内存中找到a
    2. 在寄存器中 a+1
    3. 把结果写回内存中

      对应的 汇编代码 不写了→_→(我忘了)

      

      问题: 如果 a=0,2个线程 同时执行这端代码,结果是1还是 2呢?

      看图 那么如果 核心1 和 核心2 同时 执行这段 代码(也就是 2个线程 同时执行)会发生什么………

    假设1:当线程1 执行到 读取a 时,线程2 也读取a的值,当线程1执行+1时,线程2也同操作,最后结果显而易见 是1 (当然 cpu 不会让这件事件发生。因为 他有Cache Coherence处理)

    假设2:当线程1执行完后,线程2在执行 结果就是2了。。

    再举一个例子:

    经典的 单例模式:(双检索)

     1 If(xxx==null 2 
     3 {
     4 
     5          Lock(“我是打酱油的”)
     6 
     7    {
     8 
     9            If(xxx==null)
    10 
    11      {
    12 
    13              xxx=new xxxxx();
    14 
    15       }
    16 
    17     }
    18 
    19 }

      大家都知道这个是线程安全的,但是 这种只是减少不安全的几率

      分析一下:

      这段代码执行的过程

      1、  创建对象

      2、  将对象的地址赋值给xxx

    在即时编译器 是乱序执行的,调用分配内存和调用构造函数不是一个原子操作,可能导致先执行2,在执行1,那么就报错了

    此例子来源 CLR via C#这本书,如果想详细了解请看这本书。

    当然这个话题是想引起 对 ”原子性” 讨论 。

    其实,每次我看到 原子性 都想到 线程锁,线程串行化等

    当然这种 线程安全问题 利用锁(lock关键字) 是一种很好的 解决方案,有没有 更有效地解决方法呢?

    答案是 System.Threading.Interlocked这个类

    相关的信息:http://www.cnblogs.com/mgen/archive/2013/05/27/3101755.html#_h2

    当然这个类的底层是 实现的呢 ,是这对方法: Thread.VolatileRead 和Thread.VolatileWrite

    原理:是要求cpu 每次计算完后 都直接 写入内存 ,也就不存在文章开头存在问题。

     最后 感谢 宝生兄的讲解 http://www.cnblogs.com/francisYoung/

    最后推荐 一个大神的 博客 http://www.parallellabs.com

  • 相关阅读:
    LeetCode之移除元素
    有被开心到hh(日常)
    交换排序
    插入排序
    顺序查找&折半查找
    C++之引用
    MySQL学习笔记
    C/C++程序编译过程
    计算机面试知识整合(更新中...)
    MFC之编辑框
  • 原文地址:https://www.cnblogs.com/rufus-hua/p/3440429.html
Copyright © 2011-2022 走看看