volatile关键字解析

在给 volatile关键字解析 之前 希望看本文的朋友对Java内存模型有一定的了解;不了解的朋友可以先看看Java内存模型

一、volatile关键字有什么用呢?

1、保证了不同线程访问同一个变量时的可见性,也就是说A线程修改了一个变量的值,B线程C线程能马上就能看到这个变量的最新值。

2、禁止指令的重排序。


1、volatile关键字能保证可见性吗?

看一个简单的例子:

//线程1
int i = 1;
i = 100;

//线程2
int k = i ;
如果了解Java内存模型,相信你一定可以一眼看出,在多线程的情况下,线程1的是CPU1,执行线程2的是CPU2。由上面的分析可知,当线程1执行 i =100这句时,会先把i的初始值加载到CPU1的高速缓存中,然后赋值为100,那么在CPU1的高速缓存当中i的值变为100了,却没有立即写入到主存当中。此时线程2执行 k = i,它会先去主存读取i的值并加载到CPU2的缓存当中,注意此时内存当中i的值还是0,那么就会使得 k 的值为0,而不是100,如果加了volatile 呢?

加上了volatile,就相当于给访问 volatile 修饰变量的线程 一双火眼金睛~

线程1会把volatile修饰的这个变量的每一个操作后的值都告诉主存,其他线程任何时候都可以读取到最新最正确的值;


2、volatile关键字能保证有序性吗?

看一个简单的例子:

//线程1  
resourse =  config.load(); //语句1:假设是加载一个文件完成初始化;  
boolean flag = true;//语句2   
  
//线程2  
if(flag=false){  
    Thread.sleep(1000);  
}  
add(resourse);
Java内存模型中我们举过这个例子,在多线程的情况下:如果语句2先执行了,可能导致发生异常;如果给flag变量加上volatile 关键字,volatile关键字能保证在它之前的语句1执行了,才会执行它自己语句2;
再看一个单线程的例子:

a = 1;//语句1
b = 2;//语句2
volatile boolean flag = true;//语句3
a = 4;//语句4
b = 5;//语句5
我们知道由于flag变量为volatile变量,那么在进行指令重排序的过程的时候,不会将语句3放到语句1、语句2前面,也不会讲语句3放到语句4、语句5后面。但是要注意语句1和语句2的顺序、语句4和语句5的顺序是不作任何保证的。

并且volatile关键字能保证,执行到语句3时,语句1和语句2必定是执行完毕了的,且语句1和语句2的执行结果对语句3、语句4、语句5是可见的。

3、volatile关键字能保证原子性吗?

volatile并不能保证一个操作是原子操作,为了让一个操作是原子操作可以使用synchronized关键字和Lock锁来实现;


二、volatile 使用场景

在多线程的情况下,需要进行读(获取)操作时可以使用volatile 关键字来修饰变量,在进行写操作时,还是需要使用synchronized关键字和Lock锁来实现。


举个简单的例子:concurrenthashmap 的 put 操作是要加锁才能保证把节点放进“桶”的时候是线程安全的,

而 get 操作是不需要加锁的,原因就是 节点 的属性 使用了volatile 关键字;





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值