1. volatile简介:
(1)volatile概念:
volatile是一个类型修饰符(type specfifier).它是被设计用来修饰不同线程访问和修改的变量.当一个变量被定义成volatile之后,该变量对所有线程时可见的.
(2)类的成员变量、静态成员变量被volatile修饰之后的含义:
1)保障了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这个新值对其它线程来说是立即可见的.
2)禁止进行指令重排序
2. volatile特性之:保障变量修改后立即可见.
(1)首先看一个反例,代码如下:
//线程1的核心代码
boolean isInterrupted = false;
while(!stop){
work();
}
//线程2的核心代码,将isInterrupted变量置为true,从而中断线程1的work方法
isInterrupted = true;
结果分析:
有些人在中断线程时可能都会采用这种标记办法,但是线程2却不一定会将线程中断.原因如下:
1)线程1在运行的时候,会将isInterrupted变量的值拷贝一份放在自己的工作内存当中.
2)当线程2更改了isInterrupted变量的值之后,但是还没来得及写入主存当中,那么线程1由于不知道线程2对isInterrupted变量的更改,因此还会一直循环下去,而没有中断任务.
修改方案:
使用volatile修饰变量isInterrupted,那么volatile关键字会强制将修改的值立即写入主存,那么线程1读取到的就是最新的正确的值.
修改如下:
volatile boolean isInterrupted = false;
while(!stop){
work();
}
3. volatile特性之:不能保障原子性
反面例子,代码如下:
结果分析:
执行上边的代码之后的输出,并不是10000,而是小于10000.volatile关键字虽然保障修饰过的变量对其它线程可见,但是并不保障原子性.自增操作不是原子性操作,volatile就无法保证对变量的操作是原子性的.
修改方案:
见上边的add方法,增加Synchronized关键字.
public Synchronized void add() {
number++;
}
4. volatile特性之:保障有序性
(1)volatile关键字能禁止指令重排序,因此volatile能在一定程度上保证有序性,具体是指:
1)当程序执行到volatile变量的读操作或者写操作时,在其前面的操作的更改肯定全部已经进行,且结果已经对后面的操作可见;在其后面的操作肯定还没有进行;
2)在进行指令优化时,不能将在对volatile变量访问的语句放在其后面执行,也不能把volatile变量后面的语句放到其前面执行.
(2)举例:
结果分析:
1)由于flag变量为volatile变量,那么在进行指令重排序的过程的时候,不会将语句3放到语句1、语句2前面.
2)也不会将语句3放到语句4、语句5后面.
3)但语句1和语句2的顺序、语句4和语句5的顺序是不作任何保证的.
5. volatile的适用场景:
(1)synchronized关键字是防止多个线程同时执行一段代码,那么就会很影响程序执行效率,而volatile关键字在某些情况下性能要优于synchronized.通常来说,使用volatile必须具备以下2个条件:
1)对变量的写操作不依赖于当前值
2)该变量没有包含在具有其他变量的不变式中
(2)具体举例:
1)volatile应用在状态标记量中:
2)volatile应用在双重检测中:
6. volatile与synchronized对比:
1)volatile本质是在告诉jvm当前变量在寄存器中的值是不确定的,需要从主存中读取,synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住.
2)volatile仅能使用在变量级别,synchronized则可以使用在变量,方法.
3)volatile仅能实现变量的修改可见性,而synchronized则可以保证变量的修改可见性和原子性.
4)volatile不会造成线程的阻塞,而synchronized可能会造成线程的阻塞.
更多潍坊IT培训相关资讯,请扫描下方二维码
