AQS基本的概念
AQS的全称是AbstractQueuedSynchronizer是一个抽象同步队列,它提供了FIFO队列,是一个用来实现同步锁以及其他涉及到同步功能的核心组件,常见的有:ReetrantLock、CountDownLatch等
AQS是一个抽象类,主要是通过继承的方式来使用,它本身没有实现任何的同步接口,仅仅是定义了同步状态的获取以及释放的方法来提供自定义的同步组件
lock与synchronized区别
Lock基于AQS封装的锁,结合CAS实现
Synchronized是基于C++虚拟机封装的
LockSupport用法
LockSupport可以挂起或者唤醒线程是UnSafe类实现的,park()方法会阻塞当前线程
unpark(Thread)恢复当前线程
package com.mayikt;
import java.util.concurrent.locks.LockSupport;
/**
* @Description:
* @Author: ChenYi
* @Date: 2020/07/25 15:19
**/
public class Test002 {
public static void main(String[] args) {
Thread thread = new Thread(() -> {
System.out.println("1");
LockSupport.park();
System.out.println("2");
});
thread.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程被唤醒");
LockSupport.unpark(thread);
}
}
AQS核心参数
- Node节点 采用双向链表的形式存放正在等待的线程 Thread等待锁的线程
- Head头节点 等待队列的头节点
- Tail尾节点 等待队列的尾节点
- State 锁的状态 0 无锁 1获取锁 当前线程不断的重入就会+1
- exclusiveOwerThread 记录锁的持有
Lock锁的底层
基于aqs+cas实现的,ReentrantLock默认是非公平锁,非公平锁的效率比公平锁的效率高,默认是非公平锁
公平锁
类图
流程图
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
非公平锁
类图
流程图
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
AQS中为什么头结点是为空的
头结点可以简单理解就是可以不用参加排队,表示已经获取到锁的线程,已经在aqs类中已经记录绑定获取到锁的线程,所以head结点直接设置为null,防止浪费空间内存。
参考:蚂蚁课堂