ok,先看ReentrantLock实现的接口Lock,Lock中定义了锁必须要实现的方法,总共有六个,我们使用是一般使用锁的这六个方法基本就够用了
java.util.concurrent.locks.Lock#lock
java.util.concurrent.locks.Lock#lockInterruptibly
java.util.concurrent.locks.Lock#tryLock()
java.util.concurrent.locks.Lock#tryLock(long, java.util.concurrent.TimeUnit)
java.util.concurrent.locks.Lock#unlock
java.util.concurrent.locks.Lock#newCondition
接下来看下ReentrantLock的构造方法,只有两个
private final Sync sync; //extends AbstractQueuedSynchornizer
public ReentrantLock() { //无参构造,默认为非公平锁
sync = new NonfairSync();
}
public ReentrantLock(boolean fair) { //带参构造,可以指定锁是公平的还是非公平的
sync = fair ? new FairSync() : new NonfairSync();
}
创建了对象后,就可以使用了
public void lock() {
sync.lock();
}
//直接看非公平锁的实现java.util.concurrent.locks.ReentrantLock.NonfairSync#lock
final void lock() {
if (compareAndSetState(0, 1)) //cas 修改state 的状态 ,成功就获取锁
setExclusiveOwnerThread(Thread.currentThread());//设置占有锁的线程
else
acquire(1); //尝试获取锁
}
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();//获取锁失败,并且加入队列失败
}
java.util.concurrent.locks.AbstractQueuedSynchronizer#state记录了锁的状态,重入次数 java.util.concurrent.locks.AbstractQueuedSynchronizer#tryAcquire 是一个钩子方法,真正的实现在它的子类中java.util.concurrent.locks.ReentrantLock.NonfairSync#tryAcquire
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); //重入次数加1
return true;
}
return false;
}
如果获取锁失败就会将线程加入到同步队列中排队acquireQueued(addWaiter(Node.EXCLUSIVE), arg)
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;
}
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;
}
}
}
}
java.util.concurrent.locks.AbstractQueuedSynchronizer#acquireQueued
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()) //park当前线程
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
以上就是获取锁的过程,获取不到锁线程就会阻塞,接下来看下unlock的过程
public void unlock() {
sync.release(1);
}
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h); //唤醒等待的线程
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) { //重入次数为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;
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); // 唤醒线程
}
Condition下次再学~