分类: Java
2016-07-25 15:17:10
关键字volatile可以说是Java提供的最轻量级的同步机制。Java内存模型对volatile专门定义了一些特殊的访问规则。当一个变量被定义为volatile.它有以下两种特性,1:此变量对所有的线程具有可见性。即当一个线程改变变量的属性,对其他线程这个改变后的值是立即可知的。2:禁止指令重排序优化。
但volatile变量并不能保证其在其变量在并发下是安全的。虽然其具有可见性,但是volatile变量在线程的内存并不存在一致性一说。虽然线程每次执行变量的时候都会重新刷新线程内存,但由于java里面的运算并非原子操作。导致volatile变量在并发情况下一样是不安全的。
public class VolatileTest {
public static volatile int race =0;
public static void increas(){
race++;
}
public static void main(String[] args) {
Thread th[] = new Thread[20];
for(int i=0;i<20;i++){
th[i] = new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<1000;i++){
increas();
}
}
});
th[i].start();
}
//等待所有线程都累加结束
while(Thread.activeCount()>1){
Thread.yield();
System.out.print(race+"\n");
}
}
}
运行这段代码会发现输出的值每次都不相同,并且会小于20000。通过javap -verbose反编译
当getstatic取到当前值的时候,但是并没有保证在执行iconst_1这条指令的时候,其他线程对变量已经执行加的操作了。由于volatile只能保证可见性,因此在不符合以下两种规则的时候我们任然需要加锁来保证原子性。