https://note.youdao.com/web/#/file/recent/note/E2EC87CAF0B944698A68582A58A6227B/
Java同步的设计思想
管程的设计模型,MESA模型
如何实现一把独占锁
加锁状态变量 state,0 1 , 使用 cas 实现。
等待队列:竞争锁失败的线程, 使用 Node(Thread)
等待唤醒机制:synchronized + object.wait()/object.notify()/object.notifyAll()
等待唤醒某个线程:LockSupport.park/unpark
将共性的逻辑使用模板设计模式,定义抽象类
AQS原理分析
什么是AQS
java.util.concurrent包中的大多数同步器实现都是围绕着共同的基础行为,比如等待队列、条件队列、独占获取、共享获取等,而这些行为的抽象就是基于AbstractQueuedSynchronizer(简称AQS)实现的,AQS是一个抽象同步框架,可以用来实现一个依赖状态的同步器。
AQS具备的特性:
- 阻塞等待队列
- 共享/独占
- 公平/非公平
- 可重入
- 允许中断
AQS核心结构
AQS定义两种队列
- 同步等待队列: 主要用于维护获取锁失败时入队的线程。
- 基于双向链表数据结构的队列,是FIFO先进先出线程等待队列
- AQS 依赖CLH同步队列来完成同步状态的管理
- 当前线程如果获取同步状态失败时,AQS则会将当前线程已经等待状态等信息构造成一个节点(Node)并将其加入到CLH同步队列,同时会阻塞当前线程
- 当同步状态释放时,会把首节点唤醒(公平锁),使其再次尝试获取同步状态。
- 通过signal或signalAll将条件队列中的节点转移到同步队列。(由条件队列转化为同步队列)
- 条件等待队列: 调用await()的时候会释放锁,然后线程会加入到条件队列,调用signal()唤醒的时候会把条件队列中的线程节点移动到同步队列中,等待再次获得锁。
- 调用await方法阻塞线程
- 当前线程存在于同步队列的头结点,调用await方法进行阻塞(从同步队列转化到条件队列)
ReentrantLock源码分析
ReentrantLock是一种基于AQS框架的应用实现,是JDK中的一种线程并发访问的同步手段,它的功能类似于synchronized是一种互斥锁,可以保证线程安全。
通过idea的断点进行源码分析,右键选择thread
//使用cas保证只有一个线程加锁成功
compareAndSetState(0, 1);
//作为重入锁的依据
setExclusiveOwnerThread(current);
tryAcquire(arg)
acquire(null, arg, false, false, false, 0L);