加锁操作:
final void lock() {
if (compareAndSetState(0, 1))
//CAS操作,判断当前是否有线程加过锁了,如果没有加过,设置成1代表这个线程要给它加锁了
setExclusiveOwnerThread(Thread.currentThread());
//把当前加锁对象的主人设置成当前线程
else
acquire(1);
//否则代表已经有线程加过锁了,进入后续acquire()方法判断
}
对于compareAndSetState()方法的源码:
protected final boolean compareAndSetState(int expect, int update) {
// See below for intrinsics setup to support this
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
可以看到,本质上调用的是unsafe类的compareAndSwapInt()方法。其中stateOffset代表的是在对象内存中偏移量为stateOffset的变量(也就代指的是volatile修饰的state变量)。state变量就是维护同步状态的重要变量。
进入acquire()方法:
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
这里先会进入tryAcquire()方法:
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
再进入nonfairTryAcquire()方法:
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
//获得当前线程ID
int c = getState();
//从同步器中获取到state变量,state的值代表锁已重入次数
if (c == 0) { //c为0代表还没有线程加锁
if (compareAndSetState(0, acquires)) {
//再判断一下,如果state为0,设置为1
setExclusiveOwnerThread(current); //同时设置持有该锁的线程ID
return true; //返回加锁成功
}
}
else if (current == getExclusiveOwnerThread()) {
//如果state不为0,再判断持有该锁的线程ID是否为当前线程
int nextc = c + acquires;
//如果持有该锁的线程ID为当前线程,代表发生了锁重入现象,state加1
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
//判断加锁次数是否int溢出,溢出报错
setState(nextc);
//写回state
return true; //返回加锁成功
}
return false; //返回加锁错误
}
如果加锁失败,按照
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
先进入addWaiter(Node.EXCLUSIVE)方法:
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
//创建一个新节点,线程ID为本线程ID,模式设置为null
// 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,将尾节点设置为当前线程代表的节点node
(用的是compareAndSwapObject()方法)
pred.next = node;
//设置尾节点的下一个节点为该线程代表的节点(尾插法)
return node;
//返回该节点
}
}
enq(node);
//尾节点为空表示同步队列未被初始化,此时需初始化队列
return node;
//初始化完成返回该节点
}
看看enq()方法:
private Node enq(final Node node) { //初始化队列
for (;;) { //自旋
Node t = tail;
if (t == null) { // (第一次自旋)尾节点为空,代表队列需要初始化
if (compareAndSetHead(new Node()))
//判断如果头节点为空,则初始化一个头节点
tail = head;
//让尾节点和头节点指向同一个节点
} else { // (第二次自旋)尾节点不为空,代表队列初始化过了
//往下都是尾插该节点,调整尾节点为当前节点
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t; //返回当前节点
}
}
}
}
将节点插入AQS队列后再进入 acquireQueued()方法:
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
//判断node的前驱节点是不是头节点,如果是,进入tryAcquire()方法尝试加锁
if (p == head && tryAcquire(arg)) {
//加锁成功后设置头节点
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
//如果加锁失败,则进入shouldParkAfterFailedAcquire()方法,
//如果是第一次进入该方法,该方法会将node的前驱节点的waitstatus的值改为-1并返回false,
//如果是第二次进入该方法,会直接返回true,从而进入parkAndCheckInterrupt()方法来阻塞该线程
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
解锁操作:
public final boolean release(int arg) {
if (tryRelease(arg)) { //true代表当前没有线程持有该锁
Node h = head;
if (h != null && h.waitStatus != 0)
//头节点不为空且头节点的waitStatus不为0
unparkSuccessor(h); //唤醒该节点的后继节点
return true;
}
return false; //解锁失败返回false
}
查看tryRelease()方法:
protected final boolean tryRelease(int releases) {
int c = getState() - releases; //state值减一
if (Thread.currentThread() != getExclusiveOwnerThread())
//当前线程ID不为持有锁的线程
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {
//c为0代表没有线程持有该锁
free = true;
setExclusiveOwnerThread(null);
//设置owner线程为空
}
setState(c);
//写回state状态
return free;
}