synchronized和ReentrantLock区别
-
相同点
- 都用于控制多线程对共享对象的访问
- 都是可重入锁
- 都保证了可见性和互斥性
-
不同点
- ReentrantLock显式获取和释放锁;synchronized隐式获取和释放锁。为了避免程序出现异常而无法正常释放锁,在使用ReentrantLock时必须在finally语句块中执行释放锁操作。synchronized发生异常时,会自动释放线程占用的锁,故不会发生死锁现象。Lock发生异常,若没有主动释放,极有可能造成死锁,故需要在finally中调用unLock方法释放锁;
- ReentrantLock可响应中断、可轮回,更具有灵活性
- ReentrantLock是API级别操作,synchronized是JVM级别的
- ReentrantLock可以定义公平锁
- ReentrantLock可以通过Condition绑定多个条件,仅需多次调用new Condition()即可;而在synchronized中锁锁对象的wait()、notify()/notifyAll()可以实现一个隐含的条件,如果要和多余的条件关联,就不得不额外的增加一个锁。
- 二者的底层实现不一样:synchronized是同步阻塞,采用悲观并发策略;ReentrantLock是同步非阻塞,采用乐观并发策略。
- Lock是一个接口;而synchronized是Java中的关键字,是由内至语言实现的
- 通过Lock可以知道有没有成功获取锁,synchronized不能
- Lock可以通过分别定义读写锁提高多个线程读操作的效率。ReadWriteLock就是读写锁,是一个接口,ReentrantReadWriteLock实现了这个接口。可通过readLock()获取读锁,writeLock()获取写锁。
- synchronized是非公平锁,ReentrantLock是公平锁。非公平锁可能导致有些线程永远得不到锁
性能分析:
1、大量线程同时竞争,ReentrantLock要远胜于synchronized。
2、JDK5中,synchronized是性能低效的,因为这是一个重量级操作。
3、JDK6中synchronized加入了自适应自旋、锁消除、锁粗化、轻量级锁、偏向锁等一系列优化,官方也支持synchronized,提倡在synchronized能实现需求的前提下,优先考虑synchronized来进行同步。
4、很多项目中大多使用的是synchronized