基于AQS,在并发编程中实现公平锁、非公平锁对共享资源进行同步,同时,和synchorized一样支持重入,除此之外,调度上更加灵活
ReentrantLock 实现Lock接口
加锁,一直等待,直到获取成功
加锁,一直等待,直到获取成功(假如当前线程在等待锁时被中断,则退出等待,抛出中断异常)
尝试获取锁,并立即返回
在一段时间内获取锁(假如当前线程在等待锁时被中断,则退出等待,抛出中断异常)
释放锁
新建一个绑定在当前对象上的condition对象。作用?
唯一的变量 Sync,一旦被指定,后期无法修改
抽象方法,需要NonfairSync、FairSync实现(实现是否公平的获取锁)
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
// 当前对象没有锁
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
// 判断获取锁的对象是否是当前对象
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;
}
非公平的尝试获取锁
方法含义:锁是否完全被释放。。假如:state=10, tryRelease了1次,state=9,此时返回的是false,而不是本次释放1次并且成功
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {
// 只有state=0时,才认为当前线程完全释放了锁
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
返回一个ConditionObject对象
final ConditionObject newCondition() {
return new ConditionObject();
}
获取当前锁的线程
final Thread getOwner() {
return getState() == 0 ? null : getExclusiveOwnerThread();
}
获取当前有多少线程在等待锁
final int getHoldCount() {
return isHeldExclusively() ? getState() : 0;
}
当前是否有锁
final boolean isLocked() {
return getState() != 0;
}
final void lock() {
// 尝试获取锁,如果成功,将当前锁的拥有者设置为 当前线程
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
// 获取锁失败,进入等待队列
acquire(1);
}
//
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
// 锁空闲时的处理
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
// 可重入性的判断,c表示锁被获取的次数,int最大值+1 后为负数,因此可重入的次数为int最大值
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 void lock() {
acquire(1);
}
public final void acquire(int arg) {
// 公平模式下的尝试获取锁
if (!tryAcquire(arg) &&
// 假如等待队列
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
尝试获取锁:当前锁空闲与加锁的当前线程才会获取锁成功
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
// 锁空闲 && 没有等待队列
if (c == 0) {
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;
}
state=0时,此时锁是空闲状态
公平模式:判断是否有等待队列,如果没有,才会尝试获取锁,否则tryAcquire失败 hasQueuedPredecessors()
非公平模式:不会管是否有等待队列
当前线程可能存在 在休眠线程unpark醒来之前拿到锁,在这段时间执行完,释放锁。此时休眠的线程醒来后,也能拿到锁。
在休眠线程醒来之前的时间段,已经有一个任务“加锁、执行业务逻辑、释放锁 ”,,因此性能更高