AQS与ReentrantLock

Java并发编程核心在于java.util.concurrent,JUC中大多数同步器实现都是围绕着共同的基础行为,如等待队列条件队列独占获取共享获取等,而该行为的抽象是基于AbstractQueuedSynchronizer简称AQS,AQS定义了一套多线程访问共享资源的同步器框架,是一个依赖状态state的同步器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
public abstract class AbstractOwnableSynchronizer implements java.io.Serializable {
private static final long serialVersionUID = 3737899427754241961L;
protected AbstractOwnableSynchronizer() { }
// 独占模式同步下获取锁的线程
private transient Thread exclusiveOwnerThread;
protected final void setExclusiveOwnerThread(Thread thread) {
exclusiveOwnerThread = thread;
}
protected final Thread getExclusiveOwnerThread() {
return exclusiveOwnerThread;
}
}
// AbstractQueuedSynchronizer主要属性
public class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable {
// 不管是条件队列,还是同步等待队列都是基于Node类
static final class Node {
// 标记节点为共享模式
static final Node SHARED = new Node();
// 标记节点为独占模式
static final Node EXCLUSIVE = null;
// 在同步队列中等待的线程等待超时或者被中断,需要从同步队列中取消等待
static final int CANCELLED = 1;
// 后继节点线程处于等待状态,而当前的节点如果释放了同步状态或者被取消,将会通知后继节点,使后继节点的线程得以运行。
static final int SIGNAL = -1;
// 节点在等待队列中,节点的线程等待在Condition上,当其他线程对Condition调用了signal()方法后,该节点会从等待队列中转移到同步队列中,加入到同步状态的获取中
static final int CONDITION = -2;
// 表示下一次共享式同步状态获取将会被无条件地传播下去
static final int PROPAGATE = -3;
// 标记当前节点的信号量状态 (1,0,-1,-2,-3)5种状态,使用CAS更改状态,volatile保证线程可见性,高并发场景下,即被一个线程修改后,状态会立马让其他线程可见。
volatile int waitStatus;
// 前驱节点,当前节点加入到同步队列中被设置
volatile Node prev;
// 后继节点
volatile Node next;
// 节点同步状态的线程
volatile Thread thread;
// 等待队列中的后继节点,若当前节点是共享的,则该字段是一个SHARED常量,节点类型(独占和共享)和等待队列中的后继节点共用同一个字段。
Node nextWaiter;

final boolean isShared() {
return nextWaiter == SHARED;
}

// 返回前驱节点
final Node predecessor() throws NullPointerException {
Node p = prev;
if (p == null) throw new NullPointerException();
else return p;
}
// 空节点,用于标记共享模式
Node() { // Used to establish initial head or SHARED marker
}
// 用于同步等待队列
Node(Thread thread, Node mode) { // Used by addWaiter
this.nextWaiter = mode;
this.thread = thread;
}
// 用于条件队列
Node(Thread thread, int waitStatus) { // Used by Condition
this.waitStatus = waitStatus;
this.thread = thread;
}
}
// 指向同步等待队列的头节点
private transient volatile Node head;
// 指向同步等待队列的尾节点
private transient volatile Node tail;
// 源状态:state>1:该线程重入了锁;state=1:有一个线程持有锁,exclusiveOwnerThread=该线程;state=0:没有线程持有锁
private volatile int state;

private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long stateOffset;
private static final long headOffset;
private static final long tailOffset;
private static final long waitStatusOffset;
private static final long nextOffset;

static {
try {
stateOffset = unsafe.objectFieldOffset(AbstractQueuedSynchronizer.class.getDeclaredField("state"));
headOffset = unsafe.objectFieldOffset(AbstractQueuedSynchronizer.class.getDeclaredField("head"));
tailOffset = unsafe.objectFieldOffset(AbstractQueuedSynchronizer.class.getDeclaredField("tail"));
waitStatusOffset = unsafe.objectFieldOffset(Node.class.getDeclaredField("waitStatus"));
nextOffset = unsafe.objectFieldOffset(Node.class.getDeclaredField("next"));
} catch (Exception ex) {
throw new Error(ex);
}
}
}

AbstractQueuedSynchronizer通过state字段来标记锁状态,通过CAS操作该字段以保证线程安全,通过exclusiveOwnerThread记录当前持有锁的线程通过Node队列维护所有阻塞线程,且该队列是安全的无锁阻塞队列,也是使用CAS来入队操作;通过Unsafe类提供阻塞唤醒线程的一对操作原语park/unpark来对线程进行阻塞和唤醒操作,这里使用的是LockSupport工具类,其对park/unpark原语做了封装。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public final class Unsafe {
public native void unpark(Object var1);
public native void park(boolean var1, long var2);
}
public class LockSupport {
// 当前线程调用会被阻塞,会被中断永久唤醒
public static void park() {
UNSAFE.park(false, 0L);
}
// 当前线程调用会被阻塞,会被中断唤醒一次
public static void park(Object blocker) {
Thread t = Thread.currentThread();
setBlocker(t, blocker);
UNSAFE.park(false, 0L);
setBlocker(t, null);
}
// 唤醒指定的线程
public static void unpark(Thread thread) {
if (thread != null)
UNSAFE.unpark(thread);
}
}

synchronized与AQS

synchronized不可中断不支持公平锁JVM层面上实现、代码执行完成或者出现异常会自动释放锁、不能设置超时时间,可重入、无法判断锁状态

Lock可中断、支持公平与非公平锁、通过CAS+park&unpark+链表代码层面实现、不会自动释放锁可设置超时时间、更加灵活、支持tryLock获取锁立即返回true或false、可判断锁状态、可重入

AQS具备特性

阻塞等待队列共享/独占公平/非公平可重入允许中断;除Lock外Java.util.concurrent当中同步器实现,如LatchBarrierBlockingQueue等都是基于AQS框架实现。

一般通过定义内部类Sync继承AQS将同步器所有调用都映射到Sync对应的方法,AQS内部维护volatile修饰的状态属性state32表示资源的可用状态,State三种访问方式getState()setState()compareAndSetState()

AQS定义Exclusive独占Share共享两种资源共享方式,Exclusive独占只有一个线程能执行,如ReentrantLockShare共享多个线程可同时执行,如Semaphore/CountDownLatch

不同自定义同步器争用共享资源方式也不同。自定义同步器在实现时只需要实现共享资源state的获取释放方式,具体线程等待队列的维护AQS已在顶层实现。自定义同步器实现时主要实现以下几种方法:

  • isHeldExclusively():该线程是否正在独占资源,只有用到condition才需要去实现它
  • tryAcquire(int)独占方式,尝试获取资源,成功则返回true,失败则返回false。
  • tryRelease(int)独占方式,尝试释放资源,成功则返回true,失败则返回false。
  • tryAcquireShared(int)共享方式,尝试获取资源,负数为失败;0为成功,但无剩余可用资源;正数为成功,且有剩余资源。
  • tryReleaseShared(int)共享方式,尝试释放资源,若释放后允许唤醒后续等待结点返回true,否则返回false。

AQS定义同步等待队列条件等待队列两种队列,同步等待队列FIFO先进先出线程等待队列,线程由原自旋机制改为阻塞机制

同步等待队列

Condition条件等待队列是一个多线程间协调通信的工具类,使某个或某些线程一起等待某个条件Condition,仅当该条件具备时,这些等待线程才会被唤醒,从而重新争夺锁

条件等待队列

ReentrantLock

ReentrantLock实现了Lock接口:

1
2
3
4
5
6
7
8
public interface Lock {
void lock(); // 不能被中断
void lockInterruptibly() throws InterruptedException; // 可以被中断
boolean tryLock();
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
void unlock();
Condition newCondition();
}

ReentrantLock基于AQS框架应用实现的,是JDK中线程并发访问的同步手段,其功能类似于synchronized是一种互斥锁,可保证线程安全。且具有比synchronized更多的特性,支持手动加锁解锁加锁的公平性

1
2
3
ReentrantLock lock = new ReentrantLock(false);	// false为非公平锁,true为公平锁
lock.lock() // 加锁
lock.unlock() // 解锁

ReentrantLock本身没有逻辑代码,实现都在内部抽象类Sync中,该类继承AbstractQueuedSynchronized,对该抽象类的部分方法做了实现,Sync有两个子类FairSync公平锁与NonfairSync非公平锁。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
abstract static class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = -5179523762034025860L;
// 加锁的具体行为由子类实现
abstract void lock();
// 尝试获取非公平锁 acquires = 1,默认为非公平锁实现
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
// 不需要判断同步等待队列中是否有排队等待线程,判断state状态是否为0,为0可以加锁
if (c == 0) {
// 一上来就尝试抢锁修改state值,不考虑队列中有没有其他线程排队
if (compareAndSetState(0, acquires)) { // unsafe操作,cas修改state状态
setExclusiveOwnerThread(current); // 独占状态锁持有者指向当前线程
return true;
}
}
// state状态不为0,判断锁持有者是否是当前线程,若是当前线程持有则state+1
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires; // 已经拿到锁再次重入,直接累加state变量
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false; // 加锁失败
}
// 释放锁
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); // 独占状态锁持有者置为null
}
setState(c);
return free;
}
// 判断持有独占锁的线程是否是当前线程
protected final boolean isHeldExclusively() {
return getExclusiveOwnerThread() == Thread.currentThread();
}
// 返回条件对象
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;
}
private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject();
setState(0); // reset to unlocked state
}
}

FairSync公平锁NonfairSync非公平锁也间接继承了AbstractQueuedSynchronized,ReentrantLock默认无参构造函数为非公平锁,为了提高效率,减少线程切换,也通过有参构造函数指定使用公平锁还是非公平锁。

1
2
3
4
5
6
public ReentrantLock() {
sync = new NonfairSync();
}
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}

公平锁

加锁过程

对于加锁过程公平锁与非公平锁不一样,这里的acquire(1)是AQS的模板方法tryAcquire是一个虚函数,被FairSync公平锁NonfairSync非公平锁分别实现,再次去尝试获取锁,若获取锁失败将其加入到同步等待队列中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public class ReentrantLock implements Lock, java.io.Serializable {    
public void lock() {
sync.lock();
}
}
static final class FairSync extends Sync {
private static final long serialVersionUID = -3000897897090466540L;
final void lock() {
acquire(1); // AQS的模板方法
}
// 尝试加锁,被AQS的acquire()方法调用
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
// 与非公平锁中的区别,需要先判断队列当中是否有等待的节点,没有则可以尝试CAS获取锁
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 abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable {
public final void acquire(int arg) {
// tryAcquire回调子类的FairSync的tryAcquire方法
if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
public final boolean hasQueuedPredecessors() { // 是否有排队线程
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());
}
}

首先通过addWaiter方法为当前线程创建独占模式的节点,并加入到阻塞队列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
private Node addWaiter(Node mode) {
// 将当前线程构建成Node类型
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)) { // 尝试加到队列尾部,若不成功,则执行enq(node)
pred.next = node; // 将之前的尾部节点的next执行当前的节点
return node;
}
}
enq(node);
return node;
}
// 内部会进行队列的初始化,新建一个空Node,然后不断尝试自旋,直至成功把该Node加入队列尾部
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; // 将之前的尾部节点的next执行当前的节点
return t;
}
}
}
}

已经在队列当中的Thread节点,准备阻塞等待获取锁,acquireQueued函数不会中断响应,但会记录被阻塞期间有没有收到过中断信号。因为LockSupport.park(this)可能被中断唤醒,所以acquireQueued中才写了一个for自旋,唤醒后发现自己排在队列头部尝试拿锁,若拿不到锁则再次被park阻塞

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
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)) { // 被唤醒,且若前置节点为head,尝试获取锁
setHead(node); // 拿锁成功,出队列,将head节点设置为当前节点
p.next = null; // help GC
failed = false;
return interrupted;
}
// 如果前驱节点不是Head,通过shouldParkAfterFailedAcquire判断是否应该阻塞
// 前驱节点信号量为-1,当前线程可以安全被parkAndCheckInterrupt用来阻塞线程
if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}

private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
int ws = pred.waitStatus;
if (ws == Node.SIGNAL)
return true; // 若前驱结点的状态是SIGNAL,意味着当前结点可以被安全地park
if (ws > 0) {
do { // 前驱节点状态如果被取消状态,将被移除出队列
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);
pred.next = node;
} else {
// 当前驱节点waitStatus为0 or PROPAGATE状态时,将其设置为SIGNAL状态,然后当前结点才能被安全地park
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
}
return false;
}
// 阻塞当前节点,返回当前Thread的中断状态,LockSupport.park底层实现逻辑调用系统内核功能pthread_mutex_lock阻塞线程
private final boolean parkAndCheckInterrupt() {
LockSupport.park(this);
return Thread.interrupted();
}
// 终结掉正在尝试去获取锁的节点
private void cancelAcquire(Node node) {
if (node == null)
return;
node.thread = null; // 将当前节点的线程置空
// 剔除所有被cancel的前置节点
Node pred = node.prev;
while (pred.waitStatus > 0)
node.prev = pred = pred.prev;
Node predNext = pred.next; // 前置节点的next节点
node.waitStatus = Node.CANCELLED; // 将当前节点的信号量置为CANCELLED即1
// 若当前节点为尾节点,尝试将当前节点的前置节点置为尾结点,若成功将最新的尾节点的next置为空
if (node == tail && compareAndSetTail(node, pred)) {
compareAndSetNext(pred, predNext, null);
} else {
int ws;
// 若前置节点不为head节点且前置节点为SIGNAL状态,或前置节点可被置为SIGNAL状态
if (pred != head && ((ws = pred.waitStatus) == Node.SIGNAL || (ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) && pred.thread != null) {
Node next = node.next;
// 若当前节点的next节点不为空,且不为CANCELLED状态,则将前置节点的后继节点置为当前节点的后继节点
if (next != null && next.waitStatus <= 0)
compareAndSetNext(pred, predNext, next);
} else {
unparkSuccessor(node);
}
node.next = node; // help GC
}
}

非公平锁

内部类Sync的默认实现是非公平锁ReentrantLock的无参构造方法也是非公平锁。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
static final class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L;
/**
* 第一步:直接尝试加锁,与公平锁最大的区别在于,此处不会去判断同步等待队列中是否有排队等待加锁的节点,
* 上来直接加锁(判断state是否为0,CAS修改state为1),并将独占锁持有者exclusiveOwnerThread属性指向当前线程,若当前有人占用锁,再尝试去加一次锁
*/
final void lock() {
if (compareAndSetState(0, 1)) // 直接尝试加锁,不会先去判断同步等待队列中是否有排队等待加锁的节点
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
// 父类AbstractQueuedSynchronizer.acquire()中调用本方法
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}
abstract static class Sync extends AbstractQueuedSynchronizer {
// 尝试获取非公平锁 acquires = 1,默认为非公平锁实现
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
// 不需要判断同步等待队列中是否有排队等待线程,判断state状态是否为0,为0可以加锁
if (c == 0) {
// 一上来就尝试抢锁修改state值,不考虑队列中有没有其他线程排队
if (compareAndSetState(0, acquires)) { // unsafe操作,cas修改state状态
setExclusiveOwnerThread(current); // 独占状态锁持有者指向当前线程
return true;
}
}
// state状态不为0,判断锁持有者是否是当前线程,若是当前线程持有则state+1
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires; // 已经拿到锁再次重入,直接累加state变量
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false; // 加锁失败
}
}

解锁过程

解锁过程公平锁与非公平锁一样,都是调用超类AbstractQueuedSynchronizer中的release方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
public class ReentrantLock implements Lock, java.io.Serializable {
public void unlock() {
sync.release(1);
}
}
public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable {
// 释放独占模式持有的锁
public final boolean release(int arg) {
if (tryRelease(arg)) { // 释放一次锁
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h); // 唤醒后继结点
return true;
}
return false;
}

private void unparkSuccessor(Node node) {
int ws = node.waitStatus; // 获取wait状态
if (ws < 0) // 将等待状态waitStatus设置为初始值0
compareAndSetWaitStatus(node, ws, 0);
Node s = node.next;
if (s == null || s.waitStatus > 0) { // 若后继结点为空,或状态为CANCEL(已失效)
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);
}
}
public class ReentrantLock implements Lock, java.io.Serializable {
private final Sync sync;
abstract static class Sync extends AbstractQueuedSynchronizer {
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); // 没有使用CAS,因为是排他锁,只有一个线程能执行该处,不存在竞争
return free;
}
}
}

lockInterruptibly

该方法相对于普通的获取锁的区别在于,可被中断收到中断信号不再阻塞直接抛出异常,acquireInterruptibly也是AQS中的模板方法,里面的tryAcquire方法被FairSync公平锁NonfairSync非公平锁分别实现,上面已经讲过:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class ReentrantLock implements Lock, java.io.Serializable {
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
}
}
public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable {
public final void acquireInterruptibly(int arg) throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
if (!tryAcquire(arg))
doAcquireInterruptibly(arg);
}
// 与acquireQueued逻辑相似,唯一区别节点还不在队列当中需要先进行入队操作
private void doAcquireInterruptibly(int arg) throws InterruptedException {
// 以独占模式放入队列尾部
final Node node = addWaiter(Node.EXCLUSIVE);
boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return;
}
if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt())
throw new InterruptedException(); // 收到中断信号不再阻塞,直接抛出异常
}
} finally {
if (failed)
cancelAcquire(node);
}
}
}

tryLock

tryLock()实现基于调用非公平锁的nonfairTryAcquire方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public boolean tryLock() {
return sync.nonfairTryAcquire(1);
}
// 尝试获取非公平锁 acquires = 1,默认为非公平锁实现
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
// 不需要判断同步等待队列中是否有排队等待线程,判断state状态是否为0,为0可以加锁
if (c == 0) {
// 一上来就尝试抢锁修改state值,不考虑队列中有没有其他线程排队
if (compareAndSetState(0, acquires)) { // unsafe操作,cas修改state状态
setExclusiveOwnerThread(current); // 独占状态锁持有者指向当前线程
return true;
}
}
// state状态不为0,判断锁持有者是否是当前线程,若是当前线程持有则state+1
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires; // 已经拿到锁再次重入,直接累加state变量
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false; // 加锁失败
}

带参数的tryLock(long timeout, TimeUnit unit),指定纳秒内获取不到锁就放弃锁的获取:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}

private boolean doAcquireNanos(int arg, long nanosTimeout) throws InterruptedException {
if (nanosTimeout <= 0L)
return false;
final long deadline = System.nanoTime() + nanosTimeout;
final Node node = addWaiter(Node.EXCLUSIVE);
boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return true;
}
nanosTimeout = deadline - System.nanoTime();
if (nanosTimeout <= 0L)
return false;
// 若剩余时间小于1000则直接自旋,否则通过parkNanos的方式阻塞
if (shouldParkAfterFailedAcquire(p, node) && nanosTimeout > spinForTimeoutThreshold)
LockSupport.parkNanos(this, nanosTimeout); // 阻塞nanosTimeout时间后唤醒
if (Thread.interrupted())
throw new InterruptedException();
}
} finally {
if (failed) // 若获取锁失败则放弃锁的获取,将其从队列中移除
cancelAcquire(node);
}
}