26.synchronized和ReentrantLock的区别
从锁的实现、功能特点、性能这几个方面说明:
1.锁的实现
- synchronized是Java的关键字,基于JVM实现。(可以用synchronized修饰代码块,实例方法或静态方法。)
- ReentrantLock是基于JDK的API层面实现的。(一般是lock()和unlock()方法配合try/finally语句块使用。)
2.功能特点
a.获取锁和释放锁方式不同:synchronized会自动加锁和释放锁,当进入synchronized修饰的代码块之后会自动加锁,离开时会自动释放锁;而ReentrantLock需要手动加锁和释放锁。(unlock释放锁的操作一定要放在finally中,否者有可能会出现锁一直被占用,从而导致其他线程一直阻塞的问题。)
b.锁类型不同:synchronized属于非公平锁,而ReentrantLock可以指定是公平锁还是非公平锁。
c.ReentrantLock更灵活:支持响应中断、可实现选择性通知。
(响应中断:ReentrantLock提供了一种能够中断正在等待获取锁的线程的机制,使用lockInterruptibly()获取锁并响应中断指令。而synchronized不能响应中断,也就是如果发生了死锁,使用synchronized会一直等待下去,而使用ReentrantLock可以响应中断并释放锁,从而解决死锁的问题。)
(选择性通知:ReentrantLock可以实现选择性通知(借助Condition接口和NewCondition()方法实现,在一个Lock对象中创建多个Condition实例(对象监视器),线程可以注册在指定的Condition中,signal()方法会唤醒一个等待在该Condition上的线程,而signalAll()方法会唤醒所有等待在该Condition上的线程,从而实现有选择性的线程通知。),而synchronized不行,只能随机唤醒一个线程notify(),或者全部唤醒notifyAll()。)
3.性能
在JDK1.6锁优化以前,synchronized的性能要比ReentrantLock差,但是从JDK6开始,synchronized增加了适应性自旋,锁消除等,两者之间的性能就差不多了。