比如ReentrantLock包含了AQS,内核中的锁机制实现都是依赖AQS组件的
//先来看看ReentrantLock内部怎么用AQS的
public class ReentrantLock implements Lock, java.io.Serializable {
private static final long serialVersionUID = 7373984872572414699L;//序列化标识
private final Sync sync; //用这个来继承AQS,实现基于state状态和队列来实现加锁与解锁
abstract static class Sync extends AbstractQueuedSynchronizer { /*略*/ }
//加锁方法继承了Sync的子类来实现,空参构造里面创建的就是这个
static final class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L;
final void lock() { //加锁方法
if (compareAndSetState(0, 1))//使用CAS来尝试加锁:就是当前锁的state从0变成1
setExclusiveOwnerThread(Thread.currentThread());//如果加锁成功就把当前线程设置成这把锁的独占线程
else
acquire(1); //把当前线程加入到阻塞队列
}
}
AQS是什么?JUC下同步框架的一个核心的抽象类,可以提供一个很方便的获取或释放资源的同步方式,用一个int属性来判断锁的基本状态,维护了一个先进先出的线程同步队列(加static和final修饰来保证多线程操作的可见),内部属性加了volatile也是来保证多线程操作的可见性,可有序性,在操作volatile修饰的遍历的时候会加内存屏障,同时也保证了有序性。
protected final boolean compareAndSetState(int expect, int update) {
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);//调用native方法把当前的表示从0 变成 1
}
//如果加锁失败,调用下面方法把线程放到阻塞队列
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))//这里就做把线程添加到同步等待队列
selfInterrupt(); //修改当前线程的状态
}
final boolean acquireQueued(final Node node, int arg) {//添加到队列,大致修改一下队列的相关数据 显示部分
boolean failed = true;
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();//保存
if (p == head && tryAcquire(arg)) {
setHead(node);//把这个设置成头
p.next = null; //清空下一个节点
failed = false;
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
public void unlock() { sync.release(1);} //ReentrantLock的开锁操作,调用了下面AQS的代码
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;//这里的head是同步等待队列的面第一个线程
if (h != null && h.waitStatus != 0)//下一个节点是空,状态不是0
unparkSuccessor(h); //开锁
return true;
}
return false;
}
//等待队列的头部,上面调用了
private transient volatile Node head;
//等待队列的尾部,获取锁失败的时候会添加到这个节点的后面
private transient volatile Node tail;
//表示同步状态 获取和释放锁的时候都要用
private volatile int state;
static final class Node {//部分 主要用来管理同步队列的
volatile int waitStatus;//等待状态
volatile Node prev;//上一个节点,就是线程
volatile Node next;//下一个节点
volatile Thread thread;//排队的线程
}