Java--volatile的实现原理

引入

“如果向一个变量写入值,这个变量可能会被另一个线程读取,或者在从另一个变量读值,而这个变量可能之前被另一个线程写入的。所以必须需要同步。”

有的时候为了读写一个或两个实例域就使用同步,显得开销过大。如果一个变量使用volatile,则它比使用synchronized的成本更加低。因为它不会引起线程上下文的切换和调度。

我们先从操作系统角度分析volatile:

  • 计算机在运行程序时,每条指令都是在CPU中执行的,在执行过程中势必会涉及到数据的读写。我们知道程序运行的数据是存储在主存中,这时就会有一个问题,读写主存中的数据没有CPU中执行指令的速度快,如果任何的交互都需要与主存打交道则会大大影响效率,所以就有了CPU高速缓存。CPU高速缓存为某个CPU独有,只与在该CPU运行的线程有关。
  • 有了CPU高速缓存虽然解决了效率问题,但是它会带来一个新的问题:数据一致性。在程序运行中,会将运行所需要的数据复制一份到CPU高速缓存中,在进行运算时CPU不再也主存打交道,而是直接从高速缓存中读写数据,只有当运行结束后才会将数据刷新到主存中。
  • 针对数据一致性,我们据一个例子,i++操作,当线程运行这段代码时,首先会从主存中读取i( i = 1),然后复制一份到CPU高速缓存中,然后CPU执行 + 1 (2)的操作,然后将数据(2)写入到告诉缓存中,最后刷新到主存中。其实这样做在单线程中是没有问题的,有问题的是在多线程中。如下:
    假如有两个线程A、B都执行这个操作(i++),按照我们正常的逻辑思维主存中的i值应该=3,但事实是这样么?分析如下:
    两个线程从主存中读取i的值(1)到各自的高速缓存中,然后线程A执行+1操作并将结果写入高速缓存中,最后写入主存中,此时主存i==2,线程B做同样的操作,主存中的i仍然=2。所以最终结果为2并不是3。
  • 如果要解决上述多说的数据一致性,有两种方案:
    • 通过在总线加LOCK#锁的方式:它是采用一种独占的方式来实现的,即总线加LOCK#锁的话,只能有一个CPU能够运行,其他CPU都得阻塞,效率较为低下。
    • 缓存一致性协议,它确保每个缓存中使用的共享变量的副本是一致的。其核心思想如下:当某个CPU在写数据时,如果发现操作的变量是共享变量,则会通知其他CPU告知该变量的缓存行是无效的,因此其他CPU在读取该变量时,发现其无效会重新从主存中加载数据。 (也就是说直接从主存读取数据)

从并发的三个概念角度分析volatile:

首先先分析这三个概念:
原子性: 多个线程执行一个操作时,其中任何一个线程要么完全执行完此操作,要么没有执行此操作的任何步骤,那么这个操作就是原子的。在多线程环境下,可以通过synchronized 锁机制来保证原子性。

注意volatile不是原子性的。

可见性:可见性是指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。

voliatile是可见性的

当一个变量被volatile修饰后,表示着线程本地内存无效,当一个线程修改共享变量后他会立即被更新到主内存中,当其他线程读取共享变量时,它会直接从主内存中读取。当然,synchronize和锁都可以保证可见性。

有序性:即程序执行的顺序按照代码的先后顺序执行。在Java内存模型中,为了效率是允许编译器和处理器对指令进行重排序,当然重排序它不会影响单线程的运行结果,但是对多线程会有影响。
volatile禁止指令重排序

Java提供volatile来保证一定的有序性

从java内存模型角度分析volitile

我们将 Java 内存模型中的主内存类比为 RAM(cpu主存),工作内存类比为 CPU的高速缓存。工作内存并非独立存在的一段内存空间,它是对CPU的寄存器、高速缓存及其他硬件的抽象描述。

image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米、百度、阿里、京东、新浪、CVTE、乐视家的研发岗...
    时芥蓝阅读 42,475评论 11 349
  • 感谢金总赠送的雪咖。
    铁蛋儿郭阅读 1,241评论 0 0
  • 感恩孩子们都在家对我的检验,忍不住了真就发火了,但还好及时觉察,能及时走出来及时止损,发罢火阴转晴该干啥干啥,辅导...
    寸心洁白阅读 1,144评论 0 5
  • 感觉眼睛有点点不对,明天再画一幅底稿。怕上色毁所有 后面的是重新画好的,麻烦老师帮忙看看哪个好点,谢谢
    悠悠何文阅读 4,012评论 3 0
  • 醉的朦胧 诗意朦胧 忽然发现—— 雨 停了 街灯朦胧 朕也朦胧 忽然看见—— 她 来了 不要胡思乱想 雨中的丁香一...
    姚建新阅读 2,350评论 0 0