关于.net中线程原子性的自我总结
首先来张图,一张 cpu的简图,仅从个人理解角度理解画的
大体 解释下这张图 这是 一张 i5的简图i5 大家都知道 是双核四线程,(超线程技术)l1,l2,l3是 1,2,3级缓存。
Cpu工作:每次计算任务 cpu 都去找l1,如果l1没有就去找l2,依次查找,然后依次将数据从内存加载l3,l2,l1 然后加载到 寄存器操作。
现在引入 一个问题 a+=1; 怎么执行的
首先 a+=1 是 分成 以下几部执行的
- 内存中找到a
- 在寄存器中 a+1
- 把结果写回内存中
对应的 汇编代码 不写了→_→(我忘了)
问题: 如果 a=0,2个线程 同时执行这端代码,结果是1还是 2呢?
看图 那么如果 核心1 和 核心2 同时 执行这段 代码(也就是 2个线程 同时执行)会发生什么………
假设1:当线程1 执行到 读取a 时,线程2 也读取a的值,当线程1执行+1时,线程2也同操作,最后结果显而易见 是1 (当然 cpu 不会让这件事件发生。因为 他有Cache Coherence处理)
假设2:当线程1执行完后,线程2在执行 结果就是2了。。
再举一个例子:
经典的 单例模式:(双检索)
If(xxx==null) { Lock(“我是打酱油的”) { If(xxx==null) { xxx=new xxxxx(); } } }
大家都知道这个是线程安全的,但是 这种只是减少不安全的几率
分析一下:
这段代码执行的过程
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
关于.net中线程原子性的自我总结的更多相关文章
- Java并发包中线程池ThreadPoolExecutor原理探究
一.线程池简介 线程池的使用主要是解决两个问题:①当执行大量异步任务的时候线程池能够提供更好的性能,在不使用线程池时候,每当需要执行异步任务的时候直接new一个线程来运行的话,线程的创建和销毁都是需要 ...
- java并发学习--第四章 JDK提供的线程原子性操作工具类
在了解JDK提供的线程原子性操作工具类之前,我们应该先知道什么是原子性:在多线程并发的条件下,对于变量的操作是线程安全的,不会受到其他线程的干扰.接下来我们就学习JDK中线程的原子性操作. 一.CAS ...
- synchronized使用及java中的原子性问题
1.Synchronized关键字使用 class X { // 修饰非静态方法 synchronized void foo() { // 临界区 } // 修饰静态方法 synchronized s ...
- Cocos2dx中线程优先级
Cocos2dx中线程优先级问题 不论是ios还是android,遇到耗时的任务都要另起线程处理,否则程序不能及时用户的反馈.游戏中如果一圈循环不能在1/frameRate(帧率是30则1/30)秒内 ...
- java中线程分两种,守护线程和用户线程。
java中线程分为两种类型:用户线程和守护线程. 通过Thread.setDaemon(false)设置为用户线程: 通过Thread.setDaemon(true)设置为守护线程. 如果不设置次属性 ...
- Java中线程池的学习
线程池的基本思想还是一种对象池的思想,开辟一块内存空间,里面存放了众多(未死亡)的线程,池中线程执行调度由池管理器来处理.当有线程任务时,从池中取一个,执行完成后线程对象归池,这样可以避免反复创建线程 ...
- boost中asio网络库多线程并发处理实现,以及asio在多线程模型中线程的调度情况和线程安全。
1.实现多线程方法: 其实就是多个线程同时调用io_service::run for (int i = 0; i != m_nThreads; ++i) { boo ...
- java中线程机制
java中线程机制,一开始我们都用的单线程.现在接触到多线程了. 多线性首先要解决的问题是:创建线程,怎么创建线程的问题: 1.线程的创建: 四种常用的实现方法 1.继承Thread. Thread是 ...
- worker进程中线程的分类及用途
worker进程中线程的分类及用途 欢迎转载,转载请注明出版,徽沪一郎. 本文重点分析storm的worker进程在正常启动之后有哪些类型的线程,针对每种类型的线程,剖析其用途及消息的接收与发送流程. ...
随机推荐
- 安装服务Memcached+Nginx+Php linux下安装
Memcached安装 1. 源码安装libevent(下载地址:http://monkey.org/~provos/libevent/) 2. 源码安装memcached(下载地 ...
- 【转】linux中wait与waitpid的差别
原文网址:http://blog.163.com/libo_5/blog/static/15696852010324287748/ zombie不占用内存也不占用CPU,表面上我们可以不用在乎它们的存 ...
- windows主线程等待子线程退出卡死问题
在windows下调用_beginthread创建子线程并获得子线程id(函数返回值),如果子线程很快退出,在主线程中调用WaitForSingleObject等待该线程id退出,会导致主线程卡死.需 ...
- HDU 4638-Group(线段树+离线处理)
题意: 给n个编号,m个查询每个查询l,r,求下标区间[l,r]中能分成标号连续的组数(一组内的标号是连续的) 分析: 我们认为初始,每个标号为一个组(线段树维护区间组数),从左向右扫序列,当前标号, ...
- QC开发只能修改指派给自己的缺陷,而其他的bug可以查看但是不允许修改
今天在QC9.0项目中增加了几个项目,然后我的想法是:开发只能修改指派给自己的缺陷,而其他的bug可以查看但是不允许修改 虽说qc我还是比较熟悉的,但是对于这个问题,感觉可能要用到脚本,对于脚本我一窍 ...
- 【转载】【内存对齐(二)】__declspec( align(#) )的用法和大小计算
转自:http://www.cppblog.com/deercoder/archive/2011/03/13/141747.html 感谢作者! 在上面讲到了关于pack的内存对齐和计算方法,这里继续 ...
- ORA-15005: name "orcl" is already used by an existing alias
在进行ASM操作的时候,如果目录不存在的话,那么可能会报如下的错误: <pre name="code" class="plain">RMAN> ...
- 【跟我一起学Python吧】Python解释执行原理
这里的解释执行是相对于编译执行而言的.我们都知道,使用C/C++之类的编译性语言编写的程序,是需要从源文件转换成计算机使用的机器语言,经过链接器链接之后形成了二进制的可执行文件.运行该程序的时候,就可 ...
- bzoj 4006 [JLOI2015]管道连接(斯坦纳树+状压DP)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4006 [题意] 给定n点m边的图,连接边(u,v)需要花费w,问满足使k个点中同颜色的 ...
- 题目1434:今年暑假不AC (项目安排类:结束时间快排,判断开始时间)
题目描述: “今年暑假不AC?”“是的.”“那你干什么呢?”“看世界杯呀,笨蛋!”“@#$%^&*%...”确实如此,世界杯来了,球迷的节日也来了,估计很多ACMer也会抛开电脑,奔向电视作为 ...