volatile足以保证数据同步吗

在讨论以前必须先搞清四种存储介质:寄存器、高级缓存、RAM和ROM。html

RAM与ROM你们都比较熟悉了,能够当作是咱们常常说的内存与硬盘,寄存器属于处理器里面的一部分,而高级缓存cache是CPU设计者为提升性能引入的一个缓存,也能够说是属于处理器的一部分。在利用CPU进行运算时一定涉及操做数的读取,假如CPU直接读取ROM,那么这个读取速度简直是没法忍受的,因而引入了内存RAM,这样作确实让速度提升了不少,但因为CPU发展十分迅猛而另外一方面RAM的发展受到技术及成本的限制发展缓慢,此时产生了一个很难调和的矛盾,CPU运算速度比从RAM读取数据的速度快了几个数量级,木桶原理咱们都很熟悉了,桶的容量大小取决于最短的那块,这必将影响处理器的效率,因而又引入了高级缓存,直接在CPU添加了几个级别的缓存,他们的速度虽然没法与寄存器比较,可是速度已经提高不少,基本能跟CPU的计算速度相匹配。总结成一句话就是,为了解决CPU运算速度与读取速度的矛盾,引入了多级存储机制。java

如图所示,机器的四种存储介质是有关系的,通常程序运行时会将ROM相关的程序数据都读进RAM中,而须要运算的数据或运算过程当中即将要用到的数据则会被读进高速缓存或寄存器中,假如要进行的运算所须要的全部数据及指令都在寄存器和高速缓存中,则这个运算过程则表现得很是平坦,并不存在性能瓶颈,由于运算速度跟读取速度基本匹配了。读取速度快慢的排序以下:寄存器>cache>RAM>ROM,用一个比较好理解但不彻底正确的概念来解释,由于寄存器是离CPU最近的,因此读取最快,高速缓存次之,RAM第三,ROM离得最远,天然速度最慢(固然不能彻底用距离来讲明这个问题,但用距离是比较好理解的,另外的还由于这些存储介质的硬件设计不一样、工做方式不一样)。从另外一个角度来看,CPU读取数据的顺序是先尝试读寄存器,若是不存在则尝试读高速缓存,若是还不存在则读RAM,最后才是读ROM。一些CPU有三级cache,读取时是一级一级往下直到找到须要的操做数,通常作的比较好的CPU3级缓存已经能让命中率高达95%以上。缓存

有了上面的知识再往下探索就水到渠成了,若是把Java内存模型与多级存储机制类比将发现为了提升性能java引入了工做内存的概念,提升了线程执行时读取数据的速度,这样就能够把java模型中的主存和工做内存分别于RAM和高速缓存或寄存器对应起来,每条线程的工做内存预先把须要的数据复制到高速缓存或寄存器(可是不保证全部的工做内存的变量副本都是放在高速缓存,也可能在RAM,具体的还要看JVM是如何实现的),这样在多线程并发时性能获得保证。固然寄存器和高速缓存因为成本缘由存在容量大小限制的问题,这个也是考验JVM实现的一个难题。bash

通常引入一种机制解决了一个问题,但同时也会带来另一个问题,数据同步便是带来的另外一个问题,便是否能保证当前运算使用的变量值老是当前时刻最新的值。若是变量值并不是最新值,将会致使数据的脏读,最终可能致使计算结果截然不同。这时可能有人会想起java中有个volatile关键词,毫无疑问它能保证可见性,让每一个线程获得的都是主存中最新的变量值,但它就足以保证数据的同步性了吗?举个典型例子,伪代码以下:多线程

private volatile int count=0;
private void increase(){count++}
public static void main(String args){
    建立30条线程执行;
    每条线程任务都是执行10000次increase()方法;
}复制代码

执行完全部线程任务,咱们指望的结果会是30*10000,但实际倒是一个小于30*10000的数,刚开始看到必定以为有点奇怪,但仔细一想就清楚了,count++编译后最终并不是一个原子操做,它由几个指令一块儿组合实现。下图能较清晰地说明此点,在Java内存模型中,count++被分割成5个步骤(固然这个并非确切的指令执行步骤),这5步不具备原子性,假如在完成过程当中,其余线程就去读了主存的count变量,那明显致使了一个脏读现象。并发

致使这个问题的缘由实际上是由于volatile不具有锁操做,要解决此问题其实不难,就是将这五步变为原子操做,即保证线程一完成以前不能有其余线程读取count变量,对count变量加一个互斥锁便可达到,线程一在执行第①步前对count加锁,其余线程没法对count进行访问,线程一执行完第⑤步后释放锁,此刻开始才容许其余线程获取此变量。性能

Volatile是一个很容易搞混的关键词,不少经验丰富的开发人员都不能正确使用它,这节从机器结构讲到对应的java内存模型,再引出主存与工做内存之间数据同步的问题,进而更好地解释了volatile的确切含义——它只保证可见性,它不足以保证数据的同步性。spa

========广告时间========.net

鄙人的新书《Tomcat内核设计剖析》已经在京东销售了,有须要的朋友能够到 item.jd.com/12185360.ht… 进行预约。感谢各位朋友。线程

为何写《Tomcat内核设计剖析》

=========================

欢迎关注:

这里写图片描述
这里写图片描述
相关文章
相关标签/搜索