- 整个类只有一个成员变量Sync sync,而且是内部类继承了AQS。有个抽象方法lock()。
private final Sync sync;
- 还有俩内部类,NonfairSync(非公平锁)和FairSync(公平锁),都继承了Sync;
各自实现了Sync的lock()方法 + AQS的tryAquire()方法
ReentrantLock默认是非公平锁,可以通过传参设置为公平锁
/**
*创建ReentrantLock实例 Creates an instance of {@code ReentrantLock}.
*等价于有参构造: ReentrantLock(false)}.
*/
public ReentrantLock() {
sync = new NonfairSync();
}
/**
* 有参构造
* @param fair 公平锁传入true 非公平锁传入false
*/
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
- 非公平锁lock方法解读,tryAquire方法解读,等待队列不是实体(linkedList那种),是节点组成的虚拟双向队列
final void lock() {
//先通过CAS机制尝试把AQS里面volatile修饰的state从0改成1.(0:无锁 1:有锁)
//如果CAS操作修改成功,把锁持有线程设置为当前线程
//否则通过AQS的模板方法aquire()将当前线程加入等待队列(一个Node双向链表)
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);//此方法在Sync里
}
//非公平锁尝试获取锁。
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
//无锁就加锁,设置锁持有者为当前线程,返回true,代表枪锁成功
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
//如果有锁且持有锁线程是当前线程,就(重入)把state设置为:c + acquires,返回true
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
//否则返回false(代表枪锁失败)
return false;
}
- 公平锁lock方法解读,tryAquire方法解读
final void lock() {
acquire(1);//来自AQS的acquire方法
}
//公平锁尝试获取锁方法
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
//如果锁被释放,
if (c == 0) {
如果(当前等待队列没有节点且抢锁成功)或者(锁持有者就是当前线程),返回true
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
//如果 锁没有被释放 且 锁持有者就是当前线程,重入。state设置为c + acquires
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
否则返回false
return false;
}
- 释放锁代码
public final boolean release(int arg) {
if (tryRelease(arg)) {//此方法由子类Sync实现,见下方
Node h = head;
//如果头节点不为空且waitStatus 不是0,唤醒下一个需要枪锁的线程
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
protected final boolean tryRelease(int releases) {
//计算state减1的值,还并未赋值呢
int c = getState() - releases;
//如果当前线程不是所持有线程,抛异常。因为只能自己解自己的锁
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
//资源被完全释放标志(state是0就代表完全释放)
boolean free = false;
//完全释放,把锁持有线程设置为null
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
唤醒方法unparkSuccessor()详解,为啥从队尾开始遍历?有必要了解下AQS的入队enq()
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);
}
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;
}
}
}
}
AQS中等待队列队头head和队尾tail都是被volatile修饰的。他保证了可见性。
CAS内部也是原子操作,没问题
但是上面操作CAS之外的if判断和节点next操作,并没有线程安全的保护机制。
所以每次cas之后,prev属性肯定设置完了,next可能没被设置。
所以这条双向链表,从后往前可以保证完整不遗漏;从前往后就可能next=null漏掉之后的所有节点。