转载请注明出处:http://blog.csdn.net/crazy1235/article/details/71056066
volatile只能用于修饰变量,而synchronized可以修饰方法和代码块
多线程访问volatile不会发生阻塞,而synchronized会发生阻塞
volatile只能保证数据可见性,不能保证原子性!
synchronized可以保证原子性,也可以间接保证可见性,因为它会将私有内存和公共内存中的数据做同步
volatile解决的是变量在多个线程之间的可见性;而synchronized解决的是多个线程之间访问资源的同步性
volatile的主要使用场合是再多个线程中可以感知实例变量被更改了,并且可以获得最新的值使用,也就是用多线程读取共享变量时可以获取最新值来使用
volatile每次从共享内存中读取变量,而不是从私有内存中读取,这样保证了同步数据的可见性
原子操作是不能分割的整体,没有其他线程能中断或检查正在原子操作中的变量,可以做到在没有锁的情况下线程安全!
class MyThread extends Thread{
volatile int count;
@Override
public void run() {
for (int i = 0; i < 100; i++) {
count ++;
System.out.println(Thread.currentThread().getName() + " ## "
+ count);
}
}
}
public static void main(String[] args) {
MyThread myThread = new MyThread();
Thread t1 = new Thread(myThread);
t1.start();
Thread t2 = new Thread(myThread);
t2.start();
Thread t3 = new Thread(myThread);
t3.start();
Thread t4 = new Thread(myThread);
t4.start();
}
此时输出结果是:
Thread-3 ## 3
Thread-4 ## 4
Thread-4 ## 6
Thread-4 ## 7
Thread-4 ## 8
Thread-4 ## 9
Thread-4 ## 10
Thread-4 ## 11
Thread-4 ## 12
Thread-4 ## 13
Thread-4 ## 14
Thread-2 ## 2
Thread-1 ## 2
Thread-1 ## 17
Thread-1 ## 18
Thread-1 ## 19
Thread-1 ## 20
Thread-1 ## 21
Thread-1 ## 22
Thread-1 ## 23
Thread-1 ## 24
Thread-1 ## 25
Thread-1 ## 26
class AddCountThread extends Thread {
private AtomicInteger count = new AtomicInteger(0);
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + " ## "
+ count.incrementAndGet());
}
}
}
public static void main(String[] args) {
AddCountThread countThread = new AddCountThread();
Thread t1 = new Thread(countThread);
t1.start();
Thread t2 = new Thread(countThread);
t2.start();
Thread t3 = new Thread(countThread);
t3.start();
Thread t4 = new Thread(countThread);
t4.start();
}
此时结果是:
Thread-2 ## 394
Thread-1 ## 393
Thread-2 ## 395
Thread-1 ## 396
Thread-2 ## 397
Thread-1 ## 398
Thread-1 ## 399
Thread-1 ## 400
最后累加到了400