我们都知道语言在编译和执行过程中会对自身程序进行优化
如下:
public class Test{
private static int INIT_VALUE = 0;
private final static int MAX_VALUE = 5;
public static void main(String[] args) {
new Thread(() -> {
int localValue = INIT_VALUE;
while (localValue < MAX_VALUE){
if(localValue != INIT_VALUE){
System.out.printf("The value update to [%d]",INIT_VALUE);
localValue = INIT_VALUE;
}
}
},"READER").start();
new Thread(() -> {
int localValue = INIT_VALUE;
while(localValue < MAX_VALUE){
System.out.printf("Update the value to [%d] \n", ++localValue);
INIT_VALUE = localValue;
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"UPDATER").start();
}
猜猜会输出什么:
Update the value to [1]
Update the value to [2]
Update the value to [3]
Update the value to [4]
Update the value to [5]
····
程序挂起
因为2线程启动后会更新INIT_VALUE 导致INIT_VALUE 迅速到5.
线程1 拿到的INIT_VALUE值还是0,java会内部优化此性能导致1线程 死循环
如何解决这个问题?确保INIT_VALUE能够读和写分开执行并且能够让java忽略对该属性的优化。就需要用到 volatile
package com.handsome.thread2study.chapter3;
/**
* @author jiangkunli
* @date 2020-07-01 11:47 下午
* @description
*/
public class VolatileTest {
private volatile static int INIT_VALUE = 0;
private final static int MAX_VALUE = 5;
public static void main(String[] args) {
new Thread(() -> {
int localValue = INIT_VALUE;
while (localValue < MAX_VALUE){
if(localValue != INIT_VALUE){
System.out.printf("The value update to [%d]",INIT_VALUE);
localValue = INIT_VALUE;
}
}
},"READER").start();
new Thread(() -> {
int localValue = INIT_VALUE;
while(localValue < MAX_VALUE){
System.out.printf("Update the value to [%d] \n", ++localValue);
INIT_VALUE = localValue;
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"UPDATER").start();
}
}
这样执行会发现 2线程执行+后,1线程随后就会执行updata操作,有序进行
看懂了吗?
小结:
其实
volatile关键字就是将资源锁定,同时只有一个操作来占用源,并且是有序进行。1操作、2操作、3操作、一定不会出现 1操作 1操作无序且重复调用的情况!!