Synchronized与Lock比较
1. 锁的实现
synchronized 是 JVM 实现的,而 ReentrantLock 是 JDK 实现的。
2. 性能
新版本 Java 对 synchronized 进行了很多优化,例如自旋锁等,synchronized 与 ReentrantLock 大致相同。
3. 等待可中断
当持有锁的线程长期不释放锁的时候,正在等待的线程可以选择放弃等待,改为处理其他事情。
ReentrantLock 可中断,而 synchronized 不行
4.无阻塞获取锁和锁超时响应
无阻塞获取锁-tryLock() 尝试获取锁,返回一个boolean值;
锁超时响应-tryLock(long,TimeUtil)尝试获取锁,可以设置超时
5. 公平锁
公平锁是指多个线程在等待同一个锁时,必须按照申请锁的时间顺序来依次获得锁。
synchronized 中的锁是非公平的,ReentrantLock 默认情况下也是非公平的,但是也可以是公平的。
6. 锁绑定多个条件
一个 ReentrantLock 可以同时绑定多个 Condition 对象。
总结:
Lock: 是Java中的接口,可重入锁、悲观锁、独占锁、互斥锁、同步锁。
- .Lock 是一个接口,而 synchronized 是 Java 中的关键字,
- ReentrantLock 是 API 级别的, synchronized 是 JVM 级别的
- Lock需要手动获取锁和释放锁。
- ReentrantLock 通过 Condition 可以绑定多个条件
synchronized 是内置的语言实现。
- synchronized 在发生异常时,会自动释放线程占有的锁,因此不会导致 死锁现象发生;而 Lock 在发生异常时,如果没有主动通过unLock()去释放锁,则很可能造成死锁现象,因此使用 Lock 时需要在 finally 块中释放锁。
- Lock 可以让等待锁的线程响应中断,而 synchronized 却不行,使用synchronized 时,等待的线程会一直等待下去,不能够响应中断。
- 通过 Lock 可以知道有没有成功获取锁,而 synchronized 却无法办到。
- Lock 可以通过实现读写锁提高多个线程进行读操作的效率。
- ReentrantLock 可以实现公平锁、非公平锁,默认非公平锁,synchronized 是非公平锁,且不可更改。
使用建议:
- 足够清晰简单,只需要基础的同步功能时,用synchronized。
- Lock应该确保在finally块中释放锁。如果使用synchronized,JVM确保即使出现异常,锁也能被自动释放。
- 使用Lock时,Java虚拟机很难得知哪些锁对象是由特定线程锁持有的。
除非需要使用 ReentrantLock 的高级功能,比如通过 Condition 绑定多个条件判断。否则优先使用 synchronized。这是因为 synchronized 是 JVM 实现的一种锁机制,JVM 原生地支持它,而 ReentrantLock 不是所有的 JDK 版本都支持。并且使用 synchronized 不用担心没有释放锁而导致死锁问题,因为 JVM 会确保锁的释放。