ReentrantLock
该类是可重入锁,跟synchronized 具有同样的作用,比它更具有扩展性,支持条件变量
获取互斥锁的逻辑
public void lock() {
// 调用内部类的sync 的lock方法
sync.lock();
}
Sync内部类
abstract static class Sync extends AbstractQueuedSynchronizer {
abstract void lock();
// 非公平获取互斥锁
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
// 如果没有其它线程获取锁
if (c == 0) {
// cas 原子性修改状态,如果是公平锁需要判断AQS排队队列中是否又等待的节点
if (compareAndSetState(0, acquires)) {
// 如果获取锁成功,就设置当前线程为互斥锁拥有者
setExclusiveOwnerThread(current);
return true;
}
}
// 判断当前互斥锁的拥有者是否为当前线程,如果是当前线程,ReentranLock支持锁重入
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;
}
final ConditionObject newCondition() {
return new ConditionObject();
}
}
FairSync 公平同步器
static final class FairSync extends Sync {
final void lock() {
// 调用AQS的 acquire方法
acquire(1);
}
// 公平获取互斥锁的版本
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (!hasQueuedPredecessors() && // 没有排队节点
compareAndSetState(0, acquires)// cas 更新状态
) {
// 获取锁成功,设置互斥锁拥有者
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;
}
}
NonfairSync 非公平同步器
static final class NonfairSync extends Sync {
final void lock() {
// 直接CAS ,这就是非公平锁
if (compareAndSetState(0, 1))
//获取锁成功
setExclusiveOwnerThread(Thread.currentThread());
else
// 调用AQS
acquire(1);
}
protected final boolean tryAcquire(int acquires) {
// 调用Sync内部类的非公平锁的实现
return nonfairTryAcquire(acquires);
}
}
小总结:FairSync VS NonfairSync
公平锁和非公平锁的区别在于需不需要判断AQS排队队列中是否有元素,非公平锁的直接进行CAS 修改状态,不判断队列中是否有元素,默认实现都是非公平的,因为进出队列需要花费一定的时间,线程等待和唤醒需要保存和恢复线程上下文页需要时间,CPU调度也需要一定的时间,所以非公平比公平锁性能更高
释放互斥锁逻辑--unlock
// 释放共享锁
public void unlock() {
// 调用AQS的 release方法,会调用子类的tryRelease方法
sync.release(1);
}
Sync类的 tryRelease
// 释放锁,
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
// 没有获取锁释放锁,就会报IllegalMonitorStateException 这个错误,就像在不加synchronized 调用wait()和notiyfy()方法一样
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
// 互斥锁释放完成
if (c == 0) {
free = true;
// 清空互斥锁的线程拥有者
setExclusiveOwnerThread(null);
}
// 设置状态,该操作线程安全,只有获取锁才能调用该方法
setState(c);
return free;
}
总结:
ReentranLock使用AQS的state来判断是否已经上锁,如果state>0表示该锁已经有线程获取锁了,state的数量代表重入锁的次数