(1)volatile是线程同步的轻量级实现,因此性能会比synchronized要好。volatile只能修饰变量,synchronized除了能修饰变量,还能修饰方法代码块;
(2)多线程访问volatile变量不会发生阻塞(即线程之间不会存在锁的争夺);
(3)volatile不能保证数据的原子性(这点非常重要),并不能保证线程私有内存与公共内存之间数据的同步,能做的只是保证该数据在多个线程之间的可见性(存在于公共内存中);
package com.lds.thread;
public class MyThread extends Thread{
volatile private static int count = 0;
public static void addCount(){
for(int i=0;i<1000;i++){
count++;
System.out.println("count: " + count);
}
}
public void run(){
addCount();
}
public static void main(String args[]){
MyThread[] myThreadArray = new MyThread[100];
for(int i=0;i<100;i++){
myThreadArray[i] = new MyThread();
}
for(int j=0;j<100;j++){
myThreadArray[j].start();
}
}
}
可以看到结果并非是100000!
值得注意的一点是
count++其实是分三步完成的:
1>从内存中读取count的值;
2>计算count+1的值;
3>将count的值写入内存。
该count++ 操作之所以是非线程安全的,是因为在第二步的时候很容易出现“脏读”,即在第二步计算的时候count被别的线程修改,这时会导致count计算的最后结果出现问题。还有一种常见的情形:
System.out.println("count: " + count++);
注意println( )方法是同步方法,但是count++不是同步的,因此在多线程的情况下,可能会出现意想不到的结果。