ReentrantLock
一个可重入的互斥锁 Lock
构造
public ReentrantLock() {
//默认初始化非公平的AQS
sync = new NonfairSync();
}
public ReentrantLock(boolean fair) {
//根据传入的值,选择公平还是非公平的策略
sync = fair ? new FairSync() : new NonfairSync();
}
lock
public void lock() {
//调用AQS
sync.lock();
}
final void lock() {
//更新state为1
if (compareAndSetState(0, 1))
//设置当前拥有独占访问权限的线程
setExclusiveOwnerThread(Thread.currentThread());
else
//以独占模式获取对象,忽略中断。
acquire(1);
}
public final void acquire(int arg) {
if (//是否能成功加锁
!tryAcquire(arg) &&
//阻塞获取锁
acquireQueued(
//将当前线程以及独占模式等待标记,存储到尾端节点
addWaiter(Node.EXCLUSIVE)
, arg))
//获取锁的过程中,当出现中断时,会执行到这里
selfInterrupt();
}
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) {
//这个在tryLock调用
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
//也就是这里支持重入锁
//当前线程与当前拥有独占访问权限的线程一致
//累加state
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
//返回前端节点
final Node p = node.predecessor();
/*如果是当前头节点且再次获取锁成功
*/
if (p == head && tryAcquire(arg)) {
//设置头结点为当前节点,以及清空当前节点的pre和thread
setHead(node);
//释放GC
p.next = null; // help GC
//标记正常执行
failed = false;
return interrupted;
}
//检查并修改一个节点的状态,当该节点获取锁失败时。返回true如果线程需要阻塞。
if (shouldParkAfterFailedAcquire(p, node) &&
//这里执行阻塞
parkAndCheckInterrupt())
//标记已中断
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
unlock
public void unlock() {
//释放锁
sync.release(1);
}
public final boolean release(int arg) {
if (//释放锁,成功则进入
tryRelease(arg)) {
//获取head
Node h = head;
//如果head不为空,且已经执行
if (h != null && h.waitStatus != 0)
//释放当前节点的下一个节点
unparkSuccessor(h);
return true;
}
//释放失败
return false;
}
protected final boolean tryRelease(int releases) {
//获取目前锁次数
int c = getState() - releases;
//如果当前线程不是当前拥有独占访问权限的线程,说明没有获取锁的情况下unlock,抛出异常
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
//正常释放锁
if (c == 0) {
free = true;
//清空当前拥有独占锁的线程
setExclusiveOwnerThread(null);
}
//设置锁次数
setState(c);
return free;
}
private void unparkSuccessor(Node node) {
/*
* If status is negative (i.e., possibly needing signal) try
* to clear in anticipation of signalling. It is OK if this
* fails or if status is changed by waiting thread.
*/
int ws = node.waitStatus;
//重置状态值
if (ws < 0)
compareAndSetWaitStatus(node, ws, 0);
/*
* Thread to unpark is held in successor, which is normally
* just the next node. But if cancelled or apparently null,
* traverse backwards from tail to find the actual
* non-cancelled successor.
*/
Node s = node.next;
//如果下一个节点为null,且状态取消了,则从尾端遍历,查找未取消的线程
//所以当看到next字段为null时并不意味着当前节点是队列的尾部了。
//无论如何,如果一个next字段显示为null,我们能够从队列尾向前扫描进行复核。
if (s == null || s.waitStatus > 0) {
s = null;
for (Node t = tail; t != null && t != node; t = t.prev)
if (t.waitStatus <= 0)
s = t;
}
if (s != null)
LockSupport.unpark(s.thread);
}
tryLock
public boolean tryLock() {
return sync.nonfairTryAcquire(1);
}
newCondition
public Condition newCondition() {
return sync.newCondition();
}
公平策略获取锁
final void lock() {
//以独占模式获取对象,忽略中断。
acquire(1);
}
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;
}
public final boolean hasQueuedPredecessors() {
// The correctness of this depends on head being initialized
// before tail and on head.next being accurate if the current
// thread is first in queue.
Node t = tail; // Read fields in reverse initialization order
Node h = head;
Node s;
//判断当前线程是否是等待线程节点的下一个线程
return h != t &&
((s = h.next) == null || s.thread != Thread.currentThread());
}
总结
独占锁,支持可重入,每次重入时state+1
非公平和公平获取锁的区别?
非公平获取锁的时候,不管怎么说,先去抢一波.抢不到再去抢一波,是在抢不到才会添加AQS队列等待.
而公平锁先判断是不是等待最长的线程,如果是则去抢,否则加入队列抢.