并发编程中有三个问题:原子性,可见性和有序性。
原子性:即一个操作或者多个操作要么全部执行且执行过程中不会被打断,要么就都不执行。
可见性:指多个线程访问同一变量时,一个线程修改了变量值,其他线程能够立即看到修改的值。
有序性:有序性指程序执行的顺序按照代码的先后顺序执行。
volatile不能保证原子性
如下代码示例:
public volatile int num = 0;
public void increase(){
num++;
}
public static void main(String[] args) throws InterruptedException {
VolatileTest volatileTest = new VolatileTest();
for (int i=0; i<10; i++){
new Thread(){
@Override
public void run(){
for (int j=0; j<1000; j++){
volatileTest.increase();
}
}
}.start();
}
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(volatileTest.num);
}
}
使用volatile必须具备以下2个条件:
1.对变量的写操作不依赖于当前值.
2.该变量没有包含在具有其他变量的不变式中.
volatile使用场景
运行结果发现每次都不一样,我们期望的值是:10000,导致原因如下:
自增操作不是原子性的,而且volatile也无法保证对变量操作的原子性
如想保证原子性操作可以使用如下方法:
1.increase方法前加synchronized关键字。
2.increase方法中加锁。
3.使用AtomicInteger类。