Java专题-AQS

116 阅读2分钟

AQS

AQS,Lock,Sync

tech.meituan.com/2019/12/05/…

原理:Lock-CAS Sync-monitor

1.Lock和Sync

1.自动释放锁

2.公平:默认不公平

3.可重入:都可

4.灵活:lock可以:try尝试,超时

5.lock多个条件读写分离

AQS原理

image-20220530094532038

独占模式:state设置为0

共享模式:state设置为n

整体流程

image-20220530095251039

原理

AQS中维护了一个共享资源变量 volatile int state 和一个FIFO先进先出的线程等待队列

volatile :保证线程的可见性 state= 1 代表当前对象锁已经被占有,其他线程加锁会失败,加锁失败的线程会放到FIFO等待队列中,pack()方法挂起。

state变量的操作都是通过CAS来保证并发修改的安全性

image.png

加锁过程

线程一:通过cas修改state为1,设置独占线程为当前线程

线程二:通过cas修改state为1,修改失败,执行tryAcquire方法返回false,执行addWaiter(Node.Exclusive)将自己加入Node,Node是一个双向链表即FIFO队列,WaitStatus=Signal

释放锁过程

线程一:执行完成后,会释放锁,设置state=0,释放后会唤醒head节点的后置节点,也就是线程二

线程二:CAS修改state的值,修改成功后,即获取锁成功,否则继续被挂起

非公平锁

上面所有的加锁场景都是基于非公平锁来实现的,非公平锁ReentrantLock的默认实现

原因是当线程二被唤醒,执行tryAcquire的时候,此时来了线程四,也会调用tryAcquire方法,进行竞争

公平锁

先调用hasQueuedPredecessors()方法,如果队列中没有节点,则直接获取,否则先尝试将当前线程加入到队列末尾

对比

非公平锁:减少CPU唤醒线程的开销,性能更好,会导致线程饥饿

mp.weixin.qq.com/s/trsjgUFRr…

tech.meituan.com/2019/12/05/…

zhuanlan.zhihu.com/p/97317561

pdai.tech/md/java/thr…