ReentrantLock 、Sync 、FairSync 、NonfairSync 代码之间的组织关系
public class ReentrantLock{
abstract static class Sync extends AbstractQueuedSynchronizer{
//...
}
static final class NonfairSync extends Sync {
//...
}
static final class FairSync extends Sync{
//...
}
}
Lock接口中定义了六个方法
//加锁
void lock();
//可中断的加锁
void lockInterruptibly() throws InterruptedException;
Condition newCondition();
boolean tryLock();
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
//解锁
void unlock();
加锁
ReentrantLock.lock
public void lock() {
sync.lock();
}
//这个sync是ReentrantLock中的一个属性
private final Sync sync;
//因为Sync是abstract修饰的,那么这里的Sync是哪一个子类呢?
//看构造方法,默认就是一个非公平锁
public ReentrantLock() {
sync = new NonfairSync();
}
//当然,是否公平锁是可以指定的
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
NonfairSync.lock
@Override
final void lock() {
if (compareAndSetState(0, 1)) {
setExclusiveOwnerThread(Thread.currentThread());
} else {
acquire(1);
}
}
//首先呢你看到了@Override,那么没错这个lock()就是Sync中的一个抽象方法
abstract void lock();
再来一步步看实现
1. CAS设置锁状态state的值
/**
* 如果当前状态值等于预期值,则自动将同步状态设置为给定的更新值。
* 该操作具有{@code volatile}读写的内存语义。
*
* @param expect 期待值,也就是你预想的旧值
* @param update 新的值
* @return {@code true} if successful. 返回false表示实际值与预期值不相等。
*/
protected final boolean compareAndSetState(int expect, int update) {
//unsafe的操作是native操作
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
2. 如果当前线程设置锁状态成功,说明当前线程获取锁成功,那么设置当前线程为持有锁的线程
/**
* 这个方法是AbstractOwnableSynchronizer中的
* AbstractOwnableSynchronizer是AbstractQueuedSynchronizer的抽象父类,
* 里边维护了一个代表当前单独访问的线程引用
* private transient Thread exclusiveOwnerThread;
*
*/
protected final void setExclusiveOwnerThread(Thread thread) {
exclusiveOwnerThread = thread;
}
3. 如果当前线程没有成功设置state的状态
1.尝试再次获取锁,期间要是发现加锁的线程就是当前线程,state++,也就是支持可重入
2.尝试失败,当前线程创建Node节点,然后以 『CAS + 死循环』 的方式保证放到等待队列中,同时设置当前节点为尾节点 ,
节点进入同步队列之后,就进入了一个 『自旋』 的过程,每个节点(或者说每个线程)都在自省地观察,
当条件满足,获取到了同步状态,就可以从这个自旋过程中退出,否则依旧留在这个自旋过程中(并会阻塞节点的线程)
/**
* 这个方法是AbstractOwnableSynchronizer中的
* 实现的效果就是
* 如果(尝试获取锁失败 并且 将当前线程加阻塞队列成功){
* 将当前线程中断
* }
*/
public final void acquire(int arg) {
if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt(); //Thread.currentThread().interrupt();
}
//3.1、tryAcquire(arg);
/**
* 这个方法最终到了nonfairTryAcquire这个方法
*
*/
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
//获取当前锁的状态
int c = getState();
//如果是无锁状态,也就是state为0
if (c == 0) {
//CAS设置锁状态为1,设置成功后设置当前锁的持有线程
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");
//如果是当前线程,那么state累加,这里就可以发现,Reentrant是可重入的
setState(nextc);
return true;
}
//如果是有锁状态 且 锁的持有线程不是当前线程,直接返回false,也就是线程尝试获取锁失败
return false;
}
/**
* 3.2、addWaiter(Node mode)
* 为当前线程和给定模式创建和排队节点。
* @param mode Node.EXCLUSIVE for exclusive(独占), Node.SHARED for shared(共享)
* @return 新的节点
*/
private Node addWaiter(Node mode) {
//创建一个新的node
Node node = new Node(Thread.currentThread(), mode);
/**
* 获取尾部节点
* AQS中有两个成员变量,用来表示等待队列中的头部以及尾部节点
* private transient volatile Node head;
* private transient volatile Node tail;
*/
Node pred = tail;
if (pred != null) {
//设置新节点的头结点指向原先队列的尾部节点
node.prev = pred;
//CAS设置尾节点,保证安全性
if (compareAndSetTail(pred, node)) {
//新节点的next节点指向自己
pred.next = node;
return node;
}
}
//前边的CAS可能会失败,这里通过一个死循环来保证设置尾节点一定成功
enq(node);
return node;
}
private Node enq(final Node node) {
/**
* 同步器通过“死循环”来保证节点的正确添加,在“死循环”中只有通过CAS将节点设置成为尾节点之后,当前线程才能从该方法返回,
* 否则,当前线程不断地尝试设置。可以看出,enq(final Node node)方法将并发添加节点的请求通过CAS变得“串行化”了。
*/
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;
}
}
}
}
/**
* 3.3、acquireQueued(final Node node, int arg)
*
*/
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (; ; ) {
final Node p = node.predecessor(); //就是node.prev
if (p == head && tryAcquire(arg)) {//只有node.prev是头部节点,才可以去尝试获取锁,也满足了队列的FIFO原则
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
解锁
ReentrantLock.unlock()
@Override
public void unlock() {
//每次解锁相当于state-=1 , 因为可重入的特性,state会大于1
sync.release(1);
}
//AbstractQueuedSynchronizer.release
public final boolean release(int arg) {
if (tryRelease(arg)) {
//因为ReentrantLock是支持可重入的,这里只有持有锁的线程释放掉所有的state,
//也就是state一直减到0为止,tryRelease才会返回true
Node h = head;
if (h != null && h.waitStatus != 0)
//唤醒下一个节点
unparkSuccessor(h);
return true;
}
return false;
}
//Sync.tryRelease
/**
* state是volatile修饰的一个单一变量,在具有可见性的基础上就具有了原子性
*/
@Override
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
//如果当前解锁的线程不是锁的持有线程,抛出异常
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;//标记当前线程是否完全释放锁,也就是state减为0
if (c == 0) {
//state为0,是当前线程完全释放锁标记唯一条件
free = true;
//设置当前锁持有线程为null
setExclusiveOwnerThread(null);
}
//回写state
setState(c);
return free;
}
protected final void setState(int newState) {
state = newState;
}
注意:
- 独占式锁中,线程因为获取同步状态失败之后进入同步队列中,后续对线程进行中断操作时,线程不会从同步队列中移出