Java 多线程 --- 线程同步 显式锁ReentrantLock 和 AQS机制
显式锁: Lock接口
- 显式锁是自 JDK 1.5 开始引人的排他锁。作为一种线程同步机制,其作用与内部锁相
同。它提供了一些内部锁所不具备的特性,但并不是内部锁的替代品。
- 显式锁(Explicit Lock)是
java.util.concurrent.lcoks.Lock
接口的实例。该接口对显式
锁进行了抽象
-
java.util.concurrent.lcoks.ReentrantLock
是 Lock 接口的默认实现类.
void lock() : 获取锁。
void lockInterruptibly():如果当前线程未被中断,则获取锁。
Condition newCondition(): 返回绑定到此 Lock 实例的新 Condition 买例。
boolean trylock(): 仅在调用时锁为空闲状态寸获取该锁。
boolean tryLock(long time, TimeUnit unit): 如果锁在给定的等待时间内空闲,井且当前线程未被中睡,则获取锁.
void unlock() 释放锁.
使用格式
private final Lock 1ock= ... ://创建一个Iock 接口实例
1ock.lock() //在访问共享数据前申请相应的显式锁。这一步,我们直接调用相应 Lock.lock即可
try {
//在此对共享数据进行访问
} finally{
//总是在final1y 块中释放锁,以避免锁泄漏
lock.unlock() //释放锁 lock
1
- 在临界区中访问共享数据。
Lock.lock()
调用与 Lock.unlock()
调用之间的代码区域
为临界区。不过,一般我们视上述的 try 代码块为临界区。因此,对共享数据的访问都仅放在该代码块中。
- 共享数据访问结束后释放锁。虽然释放锁的操作通过调用
Lock.unlock()
即可实现,
但是为了避免锁泄漏,我们必领将这个调用放在 finally 块中执行
- 这样,无论是临界区代码执行正常结束还是由于其抛出异常而提前退出,相应锁的 unlock 方法
总是可以被执行,从而避免了锁泄漏。可见,显式锁不像内部锁那样可以由编译器代为规避锁泄漏问题.
- ReentrantLock 既支持非公平锁也支持公平锁。ReentrantLock 的一个构造器的签名如下:
ReentrantLock (boolean fair)
- 该构造器使得我们在创建显式锁实例的时候可以指定相应的锁是否是公平锁(fair参数值true 表示是公平锁)。
- 显式锁默认使用的是非公平调度策略.
Example: 使用显示锁实现循环递增序列号生成器
public class LockbasedCircularSeqGenerator implements CircularSeqGenerator{
private short sequence = -1;
private final Lock lock = new ReentrantLock();
@Override
public short nextsequence()
lock.lock () ;
try {
if (sequence >= 999) {
sequence
}
else {
sequence--;
}
return sequence;
} finally {
lock.unlock ()
}
显性锁的实现原理 — AQS机制