介绍
jdk中独占锁的实现除了使用关键字synchronized外,还可以使用ReentrantLock。虽然在性能上ReentrantLock和synchronized没有什么区别,但ReentrantLock相比synchronized而言功能更加丰富,使用起来更为灵活,也更适合复杂的并发场景。
ReentrantLock特点
① 响应中断
可以打断应为竞争锁而进入阻塞的线程
ReentrantLock lock = new ReentrantLock();
lock.lockInterruptibly();
// 当lock所在线程竞争锁阻塞时,其他线程可以调用lock所在线程的interrupt,打断阻塞。
synchronized不可被打断。
② 锁超时
可以设置获取锁最多阻塞多长时间
ReentrantLock lock = new ReentrantLock();
// 获得锁失败,直接返回false,成功返回true
lock.tryLock()
// 第一个参数为时间,第二个参数是一个枚举类表示时间单位
lock.tryLock(long,TimeUnit)
③ 公平锁和不公平锁
默认是不公平的,所有线程随机抢到。公平锁时先阻塞的线程先抢到锁。
// 构造函数,为ture代表公平锁。不传默认false
ReentrantLock lock = new ReentrantLock(true);
大部分情况下,我们采用非公平锁,应为性能比公平锁好。但是公平锁能够避免线程饥饿,即如果申请获取锁的线程足够多,那么可能会造成某些线程长时间得不到锁。
④ Condition条件变量
ReentrantLock lock = new ReentrantLock();
Condition condition1 = lock.newCondition();
Condition condition2 = lock.newCondition();
lock.lock();
// 进入condition1等待
condition1.await()
// 唤醒该condition下的一个线程
condition1.signal();
condition1.signalAll();
await前需要获得锁,await执行后,会释放锁,进入ConditionObject等待。await的线程被唤醒(或打断、超时)重新竞争lock锁。竞争lock锁成功后,从await后继续执行
和synchronized对比
① 都是排他锁和可重入锁
② ReentrantLock可以响应中断,synchronized不可响应中断。
③ ReentrantLock可以实现公平锁,synchronized不可以实现。
④ ReentrantLock可以设置锁等待时间,synchronized不可以设置。
⑤ ReentrantLock可以使用Condition 实现线程间的等待通知机制,比synchronized使用Object的wait和notify更加灵活。