我们写一个简单实例
public class AQSTest {
static ReentrantLock lock = new ReentrantLock();
public static void main(String[] args) {
Thread thread1 = new Thread() {
@Override
public void run() {
try {
lock.lock();
System.out.println("thread1 拿锁");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
System.out.println("thread1 解锁");
lock.unlock();
}
}
};
thread1.setName("Thread1");
Thread thread2 = new Thread() {
@Override
public void run() {
lock.lock();
System.out.println("thread2 拿锁");
for (int i = 0; i < 1000; i++) {
}
System.out.println("thread2 解锁");
lock.unlock();
}
};
thread2.setName("Thread2");
thread1.start();
thread2.start();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
lock方法进入ReetrantLock的lock方法
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
1、我们发现此时我们将当前ReetrantLock对象的状态通过原子性操作CAS尝试修改(拿锁)并且设置当前的线程为currentThread(),
2、如果拿不到就进入acquire方法
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
3、我们将这个代码分成2步来看
!tryAcquire(arg)
|
|
\|/
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;
}
}
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;
}
|
|
\|/
解析: 首先拿到当前线程,然后拿到当前锁的状态,
判断一下,
如果c==0也就是无锁,我们就尝试用CAS将其设置为acquires,而这个值我们传的是1,也就是CAS修改状态(拿锁),并且返回true。
如果当前线程指向的是已经获取锁的线程,表示再次上锁,+1,
如果nextc<0,抛出异常,
重新设置锁状态,返回true
否则就是无法获取锁,返回false
|
|
\|/
第二段代码
acquireQueued(addWaiter(Node.EXCLUSIVE), arg)
|
|
\|/
解析:首先我们判断非公平锁方式是否可以拿到锁,因为 !tryAcquire(arg) --> 拿不到就是true,继续执行,拿到立刻返回
|
|
\|/
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
// Try the fast path of enq; backup to full enq on failure
Node pred = tail;
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
enq(node);
return node;
}
解析:首先我们看传入参数Node.EXCLUSIVE --> static final Node EXCLUSIVE = null;
这个源代码写的是我们传入了一个空的Node对象
首先我们创建了一个当前线程的node对象,
Node(Thread thread, Node mode) { // Used by addWaiter
this.nextWaiter = mode;
this.thread = thread;
}
构造器告诉我们传入的是后一个等待者的node,
将尾部tail--Node对象赋给pred,
如果前一个Node结点对象不为空,那么当前线程创建的node结点的前一个Node结点赋值tail(加入队列尾部),然后CAS修改前一个node结点的后继结点为当前
线程的node结点.
然后我们进入enq方法,
|
|
\|/
private Node enq(final Node node) {
for (;;) {
Node t = tail;
if (t == null) { // Must initialize
if (compareAndSetHead(new Node()))
tail = head;
} else {
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}
传入的是当前线程的node结点,这里使用的是一个空转,
反复尝试将当前node结点插入队列,
如果前一个结点为空(也就是队列未初始化),则通过CAS新建一个头node结点插入
否则,队列已经初始化好了,那么,我们将当前node结点进行尾插入队列
|
|
\|/
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)) {
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
|
|
\|/
解析: 首先传入当前node结点,arg = 1, 创建一个failed失败标记,进入try, predecessor()方法拿到前一个结点,
如果p(前结点) == 头结点,尝试给当前线程node结点加锁,
成功:当前结点前移变成头结点,删除原头结点p,修改failed失败标记为false表示加锁成功,返回中断,
unlock方法
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
解析:首先他调用了tryRelease方法,arg传参为1,
|
|
\|/
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
|
|
\|/
解析:首先传入releases参数1,拿到当前锁的状态,如果当前锁持有对象不为对应的释放锁的对象,报出非法monitor状态错误,
如果是当前线程,则创建free标记来记录是否释放成功,此时如果c的状态为0则释放锁,并且修改锁持有线程对象为null,
最后返回free
|
|
\|/
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
解析:我们回到release方法,如果没有释放锁成功,直接返回false,
如果释放锁成功,获取当前队列的头node结点,如果头结点不为null,并且等待状态不为0,我们就让他苏醒,调用unparkSuccessor
|
|
\|/
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;
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);
}
|
|
\|/
解析:首先拿到当前头结点的等待状态,如果状态小于0我们尝试CAS修改node结点(注意是node,不是ws)其状态为0,
如果头结点后面不为空,我们调用unpark方法解锁睡眠对象,这个时候,整个unlock方法就执行完了