一、AQS
AQS:AbstractQueuedSynchronizer,抽象队列同步器,是juc的基础,如常用的ReentrantLock、Semaphore、CountDownLatch、ReentrantReadWriteLock等都是基于AQS来进行设计的。
AQS通过维护一个同步状态state和一个双向队列CLH来实现加锁释放锁。
CLH队列中存放的Node结点主要关注如下几个属性:
waitStatus:等待状态,取值分别为CANCELLED = 1,SIGNAL = -1,CONDITION = -2,PROPAGATE = -3,以及初始时的0prev:当前结点的前驱结点next:当前结点的后继结点thread:当前结点对应的线程

二、加锁
lock默认为非公平锁
1、调用lock.lock()进行加锁,lock()方法内部调用sync.lock()方法进行加锁,非公平锁中,sync是NonfairSync的实例,其具体加锁代码如下
final void lock() {
// 自旋,设置AQS中同步状态 state 的值,如果 state 为0,表示当前没有线程持有锁,则将其设置为1
if (compareAndSetState(0, 1))
// 设置当前线程持有排他锁,加锁结束
setExclusiveOwnerThread(Thread.currentThread());
else
// 如果自旋失败,则表示已经有线程持有锁,state 的值不为0(大于0)
// 则通过排他模式获取锁,如果获取不成功,则进入队列
acquire(1);
}
2、acquire方法,代码如下
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
2.1、该方法的重点在于if判断,首先是 tryAcquire,在子类NonfairSync中实际调用的是nonfairTryAcquire
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
// 获取同步状态
int c = getState();
// 若同步状态为0,表示当前锁处于空闲状态
if (c == 0) {
// 尝试抢占,这里有并发的可能,所以有可能会抢不到
if (compareAndSetState(0, acquires)) {
// 如果抢到了,那就设置持有者为当前线程,并返回true
setExclusiveOwnerThread(current);
return true;

最低0.47元/天 解锁文章
1330

被折叠的 条评论
为什么被折叠?



