ReentrantLock
概述
ReentrantLock类,实现了LOck接口,是一种可重入的独占锁,它具有与使用synchronized相同的一些基本行为和语义,但功能更强大。
ReentrantLock内部通过内部类实现了AQS框架(AbstractQueuedSynchronized)的API来实现独占锁功能
ReentrantLock主要利用CAS+AQS队列来实现。它支持公平锁和非公平锁,两者的实现类似。
先通过CAS尝试获取锁;如果此时已经有线程占据了锁,那就加入AQS队列并且被挂起;当锁被释放之后,排在CLH队列对首的线程会被唤醒,然后CAS再次尝试获取锁;在这个时候,如果:
非公平锁:如果同时还有另一个线程进来尝试获取锁,那么有可能会让这个线程抢先获取:
公平锁:如果同时还有另一个线程进来尝试获取锁,当它发现自己不是在队首的话,就会排到队尾,由队首的线程先获取锁;
CAS:Compare and Swap,比较并交换。CAS有3个操作数:内存值V、预期值A、要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做。该操作是一个原子操作,被广泛的应用在Java的底层实现中。
AbstractQueuedSynchronizer简称AQS
CLH队列:带头结点的双向非循环链表(如下图所示):
ReentrantLock的实现是一种自旋锁,通过循环调用CAS操作来实现加锁;它的性能比较好也是因为避免了使线程进入内核态的阻塞状态;想尽办法避免线程进入内核的阻塞状态使我们分析和理解锁设计的关键钥匙;
ReentrantLock的基本实现
reentrantLock层次结构
reentrantLock的类层次结构图
Lock定义了锁的接口规范
ReentrantLock实现了Lock接口。
AQS中以队列的形式实现线程之间的同步
ReentrantLock的方法都依赖于AQS的实现。
Synchronized与ReentrantLock异同
相同点:
+两种同步方式有很多相似之处,它们都是加锁方式同步,而且都是阻塞式的同步
区别:
+最大区别:级别不同
++Synchronized,它是java语言的关键字,是原生语法层面的互斥,需要jvm实现。
++ReentrantLock是JDK 1.5之后提供的API层面的互斥锁,需要lock()和unlock()方法配合try/finally语句块来完成
+便利性
++Synchronized的使用比较方便简洁,并且由编译器去保证锁的加锁和释放
++ReenTrantLock需要手工声明来加锁和释放锁,为了避免忘记手工释放锁造成死锁,所以最好在finally中声明释放锁。
+锁的灵活度
++ReenTrantLock优于Synchronized
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//执行块tryLock。tryAcquire是在子类,但都需要trylock方法的不公平尝试。
final boolean nonfairTryAcquire(int acquires) {
//获取当前线程
final Thread current = Thread.currentThread();
//获取资源状态
int c = getState();
//判断是否有线程持有锁
//c == 0,则当前没有持有锁的线程
if (c == 0) {
//如果CAS成功,说明获取到锁,调用父类的setExclusiveOwnerThread方法,将独占线程设为当前线程
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
//判断是否可重入如果当前线程已经获取到锁,就更新state的值
//每获取一次锁,状态计数器 +1
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
protected final boolean tryRelease(int releases) {
//获取当前状态值减去入参releases值(1)
int c = getState() - releases;
//如果占有锁不是当前锁,则抛出异常
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
//状态值为0说明释放成功
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/**
* Sync object for non-fair locks
*/
//对非公平锁进行同步
static final class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L;
/**
* Performs lock. Try immediate barge, backing up to normal
* acquire on failure.
*/
final void lock() {
//运用到CAS理论,将状态值1
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
//覆写AQS父类的tryAcquire方法
protected final boolean tryAcquire(int acquires) {
//调用非公平尝试竞争锁方法
return nonfairTryAcquire(acquires);
}
}
/**
* Sync object for fair locks
*/
static final class FairSync extends Sync {
private static final long serialVersionUID = -3000897897090466540L;
final void lock() {
//调用父类AQS的独占锁方法
acquire(1);
}
/**
* Fair version of tryAcquire. Don't grant access unless
* recursive call or no waiters or is first.
*/
//覆写父类AQS的获取方法
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
//父类AQS的方法,获取状态
int c = getState();
if (c == 0) {
//AQS的队列是否有前驱节点
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
//设置独占锁拥有者的线程为当前线程
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
}