线程间可见性
被声明volatile关键字的变量,在多线程之间保证了变量值可见的特性,适当的使用volatile关键字,可以减少锁的使用,提升性能。
用例代码:
package cn.zealon.volatiles;
/**
* volatile特性 - 线程间共享变量
*/
public class UseVolatile implements Runnable {
//保证了stop变量的多线程之间可见性
private volatile boolean stop = true;
public boolean getStop() {
return stop;
}
public void setStop(boolean stop) {
this.stop = stop;
}
@Override
public void run() {
while (stop==true) {
System.out.println("stop:" + stop);
}
System.out.println("线程终止了。");
}
public static void main(String[] args){
UseVolatile uv = new UseVolatile();
Thread t1 = new Thread(uv);
t1.start();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
uv.setStop(false);
System.out.println("stop 设置了false");
}
}
代码中线程他t1执行后,主线程休眠2秒,然后调用了赋值函数,这时由于stop是被volatile修饰的,线程t1获取最新的stop变量的值由false变成true,所以代码执行会退出的死循环,最后线程t1也终止了。
非原子性
使用volatile关键字,需要注意重要的一点,被volatile声明的变量非原子性的。 我们例举个场景: 假设在代码中使用10个线程,同时调用一个方法对静态变量num累加操作,每次累加100;那么结果当10个线程运行结束后,num的值应该为1000。但是由于volatile关键字不是具有原子性,num的最终结果可能不是1000。
用例代码:
package cn.zealon.volatiles;
/**
* volatile特性 - 非原子性
*/
public class UseVolatile2 implements Runnable{
private static volatile int num =0;
public static void addNum(){
for (int i=0;i<100;i++){
num++;
}
System.out.println("num:"+num);
}
@Override
public void run() {
addNum();
}
public static void main(String[] args){
UseVolatile2[] useVolatile2 =new UseVolatile2[10];
for(int i=0;i<10;i++){
useVolatile2[i]=new UseVolatile2();
}
for (int i=0;i<useVolatile2.length;i++){
new Thread(useVolatile2[i]).start();
}
}
}
执行结果可能每次都不一样,可以多运行几次:
num:200
num:200
num:300
num:463
num:463
num:563
num:663
num:763
num:863
num:963
作者: Zealon
崇尚简单,一切简单自然的事物都是美好的。