对象及变量的并发访问
主要技术点:
- synchronized对象监视器为Object时的使用
- synchronized对象监视器为Class时的使用
- 非线程安全时如何出现的
- 关键字volatile的主要作用
- 关键字volatile与synchronized的区别及使用情况
synchronized同步方法
关键字synchronized拥有锁重入功能,即在使用synchronized时,当一个线程得到一个对象锁后,再次请求该对象锁时是可以再次得到该对象的锁。
可重入锁:自己可以再次获得自己的内部锁。比如有1条线程获得了某个对象的锁,此时这个对象锁还没有释放,当其再次想要获取这个对象的锁的时候还是可以获取的,如果不可锁重入的话,会造成自身的死锁。
可重入锁也支持在父子类继承的环境中。
synchronized同步块
- synchronized关键字声明的方法存在弊端:使用synchronized关键字能实现线程安全,但是缺点也很明显,必须等持有锁的对象任务完成后才能拥有锁,程序的运行时间会大大增加。
- 使用synchronized同步块,当一个线程访问object的一个synchronized同步代码块时,另一个线程仍然可以访问该对象的非同步代码块,这样便可缩短程序运行时间,提高运行效率。
- 在使用同步代码块时要注意,当一个线程访问object的一个synchronized(this)同步代码块时,其他的线程对同一个object中所有其他synchronized同步代码块将被阻塞。
- 如果synchronized加到static方法上是给Class类上锁,而加到非static静态方法上是给对象上锁。
volatile关键字
关键字volatile的主要作用是使变量在多个线程间可见。它可以强制从公共堆栈中取得变量的值,而不是从线程私有数据栈中取得变量的值。(解释:在启动线程后,变量会存在于公共堆栈和线程私有堆栈中,JVM为了提高运行效率,会一直在私有堆栈中获取对象的值,但是线程中更新对象的值却是更新的公共变量的值。)
使用volatile关键字可以使实例变量在多个线程之间可见,但是volatile的致命缺点是不支持原子性。
synchronized和volatile比较:
- 关键字volatile是线程同步的轻量级实现,执行效率比synchronized高,但是volatile只能用于修饰变量,而synchronized可以修饰方法,代码块;
- 多线程访问volatile不会发生堵塞,而访问synchronized会发生堵塞;
- volatile能保证数据的可见性,但不支持原子性;
- 关键字volatile解决的是变量在多个线程之间的可见性,而synchronized关键字解决的是多个线程之间访问资源的同步性。
同步性:互斥行和可见性。synchronized可以保证在同一时刻,只有一个线程执行某一个方法或者某一个代码块。