Volatile用法和原理

前言

  Volatile的关键字从Java5出现后就存在了,很多人做了很长时间的Java开发都未必用的到这个关键字,其实它还是很有用的一个关键字。

正文

简单概述

  volatile是Java提供的一种轻量级的同步机制,同synchronized相比,volatile更轻量级,在访问volatile变量时不会执行加锁操作,因此也就不会使执行的线程阻塞。

变量不加volatile

问题1 可见性问题

  CPU每次执行指令的时候会对内存进行读写操作,尽管内存的读写速度比硬盘的读写速度快得多,但是指令的处理速度更快,从内存进行读写速度相对于指令执行的速度就慢了,所以CPU就会将线程用到的变量以及一些复杂的操作复制到缓存(寄存器)中处理,然后再将处理的结果写入内存。但是对于多核CPU,线程可能运行在不同的CPU缓存中,这样的话就无法保证线程的可见性(指线程之间的可见性,一个线程修改的变量后,另一个线程取到变量也是修改后的变量)

image.png

//初始化
int i =10;
//每个线程都对i++
i++;

  对于i来说,线程A从内存读取i后存入缓存,它取到的值是10,线程B也将i从内存中读入缓存,取到值也是10。线程A对i++,i就变成了11,但是线程B中的i还是10,那么i变量对于线程是不可见的了。

问题2 有序性问题
int i = 0;//A步骤
int j = 1;//B步骤
i++;//C步骤
j++;//D步骤

  CPU为了保证性能或者在多个线程存在的情况下,对于指令的处理顺序会有变化(指令重排序:CPU允许将多条指令不按程序规定的顺序分别给各个相应的处理器处理),比如它可能先执行了B步骤,然后在执行A步骤,也可能先执行了D步骤,然后再执行C步骤。

变量加volatile

线程可见性
//初始化
volatile int i =10;

  对于一个变量赋予了volatile关键字后那么变量对所有的线程具有可见性,当一个线程修改了这个变量的值,编译器就不会将这个变量复制到缓存中,就直接在内存中操作,这样从内存中取到的volatile标识的变量就是最新的值,也就对其它线程可见了。

image.png

线程有序性

  volatile可以禁止指令重排序,volatile标识的变量,会有内存屏障,指令重排序时就不能把后面的指令重排序到内存屏障之前的位置,这样就保证不同的代码块只能串行执行,不能同步执行,这样就保证了线程的有序性。

volatile缺点

volatile不能保证原子性,volatile可以配合synchronized保证原子性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值