Java并发编程:volatile与synchronized的区别小结

来源:互联网 发布:二次元背景拍照软件 编辑:程序博客网 时间:2024/04/30 15:56

1、锁提供了两种主要特性:互斥(mutual exclusion) 和可见性(visibility)。互斥即一次只允许一个线程持有某个特定的锁,因此可使用该特性实现对共享数据的协调访问协议,这样,一次就只有一个线程能够使用该共享数据。可见性要更加复杂一些,它必须确保释放锁之前对共享数据做出的更改对于随后获得该锁的另一个线程是可见的 —— 如果没有同步机制提供的这种可见性保证,线程看到的共享变量可能是修改前的值或不一致的值,这将引发许多严重问题。

2、在Java中为了保证多线程读写数据时保证数据的一致性,可以采用两种方式

1)同步

使用synchronized关键字,或者使用锁对象(如互斥锁ReentrantLock)。

一个线程执行互斥代码过程如下:

a. 获得同步锁; 
b. 清空工作内存; 
c. 从主内存拷贝对象副本到工作内存; 
d. 执行代码(计算或者输出等); 
e. 刷新主内存数据; 
f. 释放同步锁。 

2)使用volatile关键字(关于volatile关键字详解,请查看volatile关键字解析)。

volatile与synchronized比较
volatile本质是在告诉jvm当前变量在寄存器中的值是不确定的
需要从主存中读取synchronized则是锁定当前变量只有当前线程可以访问该变量其他线程被阻塞住
volatile仅能使用在变量级
synchronized则可以使用在变量方法
volatile仅能实现变量的修改可见性
但不具备原子特性而synchronized则可以保证变量修改可见性和原子性
volatile不会造成线程的阻塞
而synchronized可能会造成线程的阻塞
volatile标记的变量不会被编译器优化
而synchronized标记的变量可以被编译器优化

3、因此,在使用volatile关键字时要慎重,并不是只要简单类型变量使用volatile修饰,对这个变量的所有操作都是原来操作,当变量的值由自身的上一个决定时,如n=n+1、n++ 等,volatile关键字将失效,只有当变量的值和自身上一个值无关时对该变量的操作才是原子级别的,如n = m + 1,这个就是原级别的。所以在使用volatile关键时一定要谨慎,如果自己没有把握,可以使用synchronized来代替volatile。
总结:volatile本质是在告诉JVM当前变量在寄存器中的值是不确定的,需要从主存中读取。可以实现synchronized的部分效果,但当n=n+1,n++等时,volatile关键字将失效,不能起到像synchronized一样的线程同步的效果。

0 0
原创粉丝点击