Volatile vs. Interlocked vs. lock
今天在stackoverflow上看到一个关于Volatile, Interlock, Lock的问题,发现回答的特别好,所以就想到把它翻译一下, 希望给那些对它们有疑惑的人提供点帮助
:假设有一个类,它含有一个可以被多线程访问的public int counter 字段, 这个数字只会增加或减少。
当去增加这个字段的时候,应该采用下面哪个方案,为什么?
- lock(this.locker) this.counter++;
- Interlocked.Increment(ref this.counter);
- Change the access modifier of counter to public volatile
:
最糟糕(实际上都不能起作用)
Change the access modifier of counter to public volatile
这种方式实际上根本不安全,关于volatile的重点是:运行在多个CPU上的多个线程会缓冲数据和重新排列执行的指令。
如果它是非volatile, 当CPU A增加了一个值, CPU B需要等一会才能看到增加的值,这可能导致问题的出现。
如果它是volatile,就能确保两个CPU能在相同的时间看到相同的值。但它并不能避免交叉的读写操作。
给一个变量增加值,实际上需要三步
1. 读, 2. 增加 3.写
假设线程A 读取 counter 的值为1,还没有准备增加,这时线程B也读取counter 的值为1, 然后两个线程都开始执行增加,写的操作。最终counter 的值为2. 这是不对的,两个线程都做了增加操作,正确的结果应该是3. 所以把它标志为volatile根本就是不安全的。
比较好
lock(this.locker) this.counter++;
这种方式是安全的(当然你要记得lock所有你想访问this.counter的地方)。它防止其它任何线程去执行被lock锁住的代码。并且它还能防止上面提到的多CPU指令排序的问题。但问题是,lock在性能上比较慢,并且如果你在其它的一些不相干的地方也用了lock,可能会导致阻塞你的其它线程。
最好
Interlocked.Increment(ref this.counter);
这个是安全的,也是非常高效的。它执行读,增加,写三个操作在一个原子中,不会在中间被打断。因为它不影响其它的代码,你也不需要记住其它地方的Lock. 并且它还非常快(正如MSDN说的,在现在的CPU上,它常常只是一个指令)。
但是我不完全确定它能否也能解决CPU的指令排序的问题,还是需要结合volatile和这个increment一起使用。
补充:到底volatile是擅长解决什么问题的?
既然volatile不能防止多线程的问题,那它能干啥用?举个很好的例子,假设你有两个线程,一个总是往一个变量中进行写操作,假设这个变量为queneLength, 另一个总是从这个变量中读取数据。如果queueLenght不是volatile的, 线程A可能读了5次,但是线程B可能看到的是延迟的数据,甚至可能看到错误的顺序的数据。一个方案就是用lock, 但是在这种情况系你也可以用volatile. 这样能确保线程B总能看到线程A写的最新数据,但是这个这个逻辑仅仅在你写的时候没有读,读的时候没有写时才有效。一旦多个线程都要做读-修改-写的操作,你需要用Interlocked或者用lock.
Volatile vs. Interlocked vs. lock的更多相关文章
- 多线程中的锁系统(二)-volatile、Interlocked、ReaderWriterLockSlim
上章主要讲排他锁的直接使用方式.但实际当中全部都用锁又太浪费了,或者排他锁粒度太大了,本篇主要介绍下升级锁和原子操作. 阅读目录 volatile Interlocked ReaderWriterLo ...
- 多线程---再次认识volatile,Synchronize,lock
在多线程中我们常用的保证共享变量的方法有很多,现在我们介绍其中的一种,volatile,也是效率最高的一种. 一 .volatile的意义: 为了确保共享变量能被正确和一 ...
- volatile和synchronized与lock的理解
volatile 特征: a:可见性:一个线程修改了某个共享变量的值,其他线程能够立马得知这个修改. b:禁止特定的处理器重排序. volatile的内存语义: 1.当写一个volatile变量的时候 ...
- volatile 和 Interlocked
class Volatile_Test3 { ; public static void Test() { count = ; Task[] tasks = ]; ; i < tasks.Leng ...
- volatile、synchronized、lock有什么区别,以及在哪些场景下使用哪种方式?
[转]JVM锁机制volatile/synchronized/lock 1.volatile实现原理 (1)聊聊并发(一)——深入分析Volatile的实现原理 --硬件级别锁实现,Lock前缀指令会 ...
- Java并发编程知识点总结Volatile、Synchronized、Lock实现原理
Volatile关键字及其实现原理 在多线程并发编程中,Volatile可以理解为轻量级的Synchronized,用volatile关键字声明的变量,叫做共享变量,其保证了变量的“可见性”以及“有序 ...
- 线程、volatile与synchronized、Lock
目录 线程 1.概念: 2.线程生命周期: 3.线程调度 4.线程实现 4.1.实现方式 4.2.之间的区别: 5.线程安全 5.1.volatile与synchronized 5.1.synchro ...
- C# 基础回顾: volatile 关键字
有些人可能从来没看到过这个关键字,这也难怪,因为这个关键字并不常用.那这个关键字到底有什么用呢? 我在网上搜索这个关键字的时候,发现很多朋友都有一个错误的认识 ------ 认为这个关键字可以防止并发 ...
- C# Interlocked 笔记
无锁代码下,在读写字段时使用内存屏障往往是不够的.在 64 位字段上进行加.减操作需要使用Interlocked工具类这样更加重型的方式.Interlocked也提供了Exchange和Compare ...
随机推荐
- Eclipse3.7默认字体修改-找回Courser-New字体
1.找到jFace并用WinRAR打开之: jFace的具体位置:$Eclipse目录$/plugins/org.eclipse.jface_3.7.0.I20110522-1430.jar,找到后, ...
- windows10UWP:如何在xaml中设置控件为 public ?
windows10UWP中,由于使用页面导航,操作在不同一个页面的控件需求经常遇到. 如果要对另一个page里面的控件进行操作,那么这个控件必须设置为 public .在 xaml 设置控件的方法是: ...
- 关于弹出层(iframe)时刷新页面的js
[javascript] view plaincopyprint? iframe弹出子页面刷新父页面iframe parent.location.reload(); [javascript] view ...
- 使用EasyUI设计.net项目的菜单数实例
最近领导说我们之前的项目采用的菜单树模型过时了,现在采用EasyUI来设计了,于是学习了第三方资源库easyUI,发觉果然是好东西,这里给大家分享下. 首先到官网下载源文件,这个是开源的,都可以下再, ...
- (ternary operator)三元运算符.
ternary operator: advantage: make a terse simple conditional assignment statement of if-then-else. d ...
- html招聘简历解析并入库测试
1.解析4天,一天用来熟悉Jsoup 2.入库,需要熟悉什么样的格式代码可以入库,将自己解析好的代码转为指定格式.总体框架的构建, 如何执行,需要读他人写的代码(很费时间).4天,包括晚上九点加班三天 ...
- X3850 Linux 下DSA日志收集办法
收集工具下载 RHEL 6: 32bit-- [IBM 下载]http://delivery04.dhe.ibm.com/sar/CMA/XSA/03tza/1/ibm_utl_dsa_dsytb7x ...
- C++ Reference 的“三位一体”诠释
C++ 是介于汇编语言与高级语言之间的一种“全能”语言.它的能力是其他任何基于VMA(冯-诺曼架构)计算机的高级程序设计语言无法望其项背的,而性能也只有C语言可与之伯仲. 然而长期以来,喜欢C++和憎 ...
- 【BZOJ2741】【块状链表+可持久化trie】FOTILE模拟赛L
Description FOTILE得到了一个长为N的序列A,为了拯救地球,他希望知道某些区间内的最大的连续XOR和. 即对于一个询问,你需要求出max(Ai xor Ai+1 xor Ai+2 .. ...
- Python中%s和%r的区别
早先使用Python工作的时候,对于格式化输出%s和%r的使用都是混着用的. 这一次就出错了: cu.execute("insert into ipPool values(null, '%r ...