JAVA并发编程
5. 显式锁
5.1 Lock接口
5.1.1 概念
- Lock接口提供了无条件的、可轮询的、定时的、可中断的锁获取操作
- 加锁和解锁的方法都是显式的
- 优点:可以中断等待获取锁的线程;可以不必无限等待锁
5.1.2 方法
方法 | 返回值 | 描述 |
---|---|---|
lock() | void | 申请锁,一直到锁可用 |
lockInterruptibly | void | 当前线程未被中断则申请锁,否则抛出异常 |
tryLock() | boolean | 只在调用时申请锁 |
tryLock(long, TimeUnit) | boolean | 在一段时间内申请锁 |
unlock() | void | 释放锁 |
newCondition() | Condition | 返回一个新Condition绑定到该实例Lock 实例 |
5.1.3 使用规范
Lock lock = new ReentrantLock();
lock.lock();
try{
//do something
} finally{
lock.unlock();
}
5.2 ReentrantLock
5.2.1 概念
-
tryLock()实现了可定时的和可轮询的锁获取模式,可以避免死锁。
(避免死锁:将不同锁的trylock()方法作为嵌套的if判断条件,即只有获得锁1才能获得锁2)
-
在等待锁的过程中,程序可以取消对锁的请求(lockInterruptibly())。
5.2.2 Condition
-
newCondition()方法返回该锁的Condition对象,实现等待通知
-
方法
方法 返回值 描述 await() void 使线程等待并释放锁,知直到被通知或中断 await(long, TimeUnit) boolean 使线程等待一段时间内被通知、中断 awaitUninterrputibly() void 使线程等到被通知 awaitUntil(Date) boolean 使线程等待到某个时刻前被通知、中断 signal() void 通知唤醒一个等待线程 signalAll() void 通知唤醒所有等待线程
5.2.3 其他方法
方法 | 返回值 | 描述 |
---|---|---|
isHeldByCurrentThread() | boolean | 查询此锁是否由当前线程持有 |
isLocked() | boolean | 查询此锁是否由任何线程持有 |
isFair() | boolean | 查询是否为公平锁 |
… | … | … |
5.2.4 公平性
-
公平锁:公平锁会让新的请求线程加入等待队列,线程按照时间顺序获得锁。
-
非公平锁:从阻塞队列中随机选择一个线程恢复,性能较高。
synchronized是非公平锁,ReentrantLock默认是非公平锁。
5.3 ReentrantReadWriteLock
5.3.1 概念
-
ReentrantLock是互斥锁,同一时间只能被一个线程持有
-
ReadWriteLock接口允许多个线程同时读取,但不能同时读写或同时写。
-
ReentrantReadWriteLock实现了ReadWriteLock接口
5.3.2 接口方法
方法 | 返回值 | 描述 |
---|---|---|
readLock() | Lock | 返回读锁 |
writeLock() | Lock | 返回写锁 |
5.2.3 实现
ReadWriteLock lock = new ReentrantReadWriteLock();
Lock r = lock.readLock();
Lock w = lock.writeLock();
r.lock();
try{
// do something
} finally{
r.unlock();
}
w.lock();
try{
// do something
} finally{
w.unlock();
}