新建Lock时,ReentrantLock默认使用非公平锁进行同步:
public ReentrantLock() {
sync = new NonfairSync(); // NonfairSync是内部类,实现了Syn内部抽象类
}
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync(); // true为公平锁,false为非公平锁
}
当生成锁后,就可以使用lock()进行线程同步,NonfairSync会先用cas判断锁状态,cas判断失败才会调用acquire(),而FairSync则会直接调用acquire()。ReentrantLock是可重入锁,可以被单个线程多次获取,每获取1次就将锁的状态+1。状态默认为0。由于存在两种锁类型,接下来,将优先了解非公平锁重要方法的源码:
final void lock() {
if (compareAndSetState(0, 1)) // 使用cas机制竞争锁的拥有权
setExclusiveOwnerThread(Thread.currentThread()); // 设定获得当前锁的线程
else
acquire(1);
}
acquire()的实现代码:
public final void acquire(int arg) {
if (!tryAcquire(arg) && // 尝试获取锁
acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) // 创建一个入队node为当前线程,Node.EXCLUSIVE 是独占锁, Node.SHARED 是共享锁,将线程加入到CLH队列(非阻塞的FIFO队列)末尾。CLH队列就是线程等待队列。
selfInterrupt(); // 在休眠等待过程中被中断过,acquireQueued会返回true,线程会调用selfInterrupt()中断等待。
}
首先实行了tryAcquire()尝试获取锁的拥有权,该方法会使用cas机制判断当前的锁是否被拥有,如果当前锁未被拥有,则设置当前线程获得锁;如果被当前线程拥有,则设置state值+1;如果被其他线程拥有则返回false。实现代码如下:
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires); // 调用ReentrantLock的Syn抽象内部类
}
tryAcquire()会调用Syn抽象内部类中的nonfairTryAcquire()方法,如果该锁是FairSync则不会调用nonfairTryAcquire(),而是直接覆盖tryAcquire()。
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread(); // 获取当前线程
int c = getState(); // 获取锁的状态值
if (c == 0) {
if (compareAndSetState(0, acquires)) { // 如果在cas机制中竞争成功,则设置当前线程获得锁,返回true
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;
}
可以看到ReentrantLock可以被单个线程多次获取,每获取1次就将锁的状态+1。
protected final boolean tryRelease(int releases) {
int c = getState() - releases; // 减少状态值
if (Thread.currentThread() != getExclusiveOwnerThread()) // 判断线程是否拥有锁的线程
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) { // 状态值为0,设置锁的所属线程为null
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
ReentrantLock释放锁时,会为当前锁的状态值-1,直到状态值为0时,才会释放锁的控制权。
创建Condition,一个ReentrantLock可以有多个Condition实例,可实现分组的等待和唤醒:
final ConditionObject newCondition() {
return new ConditionObject();
}
hasQueuedThread()和hasQueuedThreads():
hasQueuedThread(Thread thread) 查询指定的线程是否正在等待获取当前的锁。
hasQueuedThreads() 查询是否有线程正在等待获取当前的锁。
getQueueLength():
获取正在等待获取锁的线程数。
getQueuedThreads():
获取正在等待的线程,返回Collection<Thread>。
hasWaiters(Condition condition):
判断绑定了同一个Condition的线程,是否都处于await()状态。
getWaitQueueLength(Condition condition):
获取绑定了用一个Condition,并且处于await()状态的线程数量。
getWaitingThreads(Condition condition):
获取绑定了用一个Condition,并且处于await()状态的线程,返回Collection<Thread>。