ReentrantLock、synchronized 与 ReadWriteLock
一. ReentrantLock
ReentrantLock 并不是内置锁 synchronized 的替代方式,而是当 synchronized 加锁机制不适用时,作为一种可选择的高级功能。
ReentrantLock 是 Lock 的实现类,Lock 提供无条件的、可轮询的、定时的以及可中断的锁获取操作,所有加锁和解锁的方法是显式的,因此 ReentrantLock 也被称为显示锁。
1. Lock 的源码
1 | public interface Lock { |
2. ReentrantLock 的用法
2.1 ReentrantLock 的标准用法
1 | // Lock 的标准用法 |
2.2 ReentrantLock 带时间的加锁
1 | // 带有时间限制的加锁 |
二. Synchronized
使用了 synchronized 方法在同一时间只能被一个线程使用,其他线程必须等到这方法释放。
线程在进入了同步代码块之前会自动获得锁,并且在退出同步代码块时自动释放锁。
同步代码块包含两部分
- 一个作为锁的对象引用
- 一个作为由这个锁保护的代码块
两种使用方法
- 以锁的对象使用
1 | private Object lock = new Object(); |
- 锁保护的代码块
1 | // 锁保护代码块 |
- Class对象锁
1 | public static EventBus getDefault() { |
三. Synchronized 与 ReentrantLock 之间选择
synchronized
- 开发人员熟悉,简洁紧凑
- 不用担心解锁的问题
- 在线程转储中能给出在哪些调用帧获得了哪些锁,并能检测和识别发生了死锁的线程
ReentrantLock
- 提供了可定时的、可轮询的与可中断的锁
- 如果忘记 unlock, 会发生死锁的问题
选择
在 synchronized 无法满足的情况下才会使用 ReentrantLock
3. ReadWriteLock 读写锁
- 当读线程多于写线程时,使用 ReadWrite 线程会更好一些
- ReentrantReadWriteLocks 可以用作提高一些并发容器的性能
当锁的持有时间比较长并且大部分操作都不会修改被守护资源是,ReadWriteLock 能提高并发性
ReadWriteLock 接口
1 | public interface ReadWriteLock { |
- 提高一些并发容器的性能
1 | /** |