Synchronized 和 AQS 实现要点
所属分类 java
浏览量 1277
锁机制两种基本形式 阻塞 和 自旋(CAS)
对象监视器上只能拥有一个同步队列和一个等待队列,并发包中的Lock可以拥有一个同步队列和多个等待队列
Synchronized 基于 Java对象头 和 Monitor机制 实现
对象在内存中包含三部分 对象头 实例数据 和 对齐填充
Class Metadata Address (类型指针) 通过该指针定位是哪个类的实例
Mark Word(标记字段) 对象运行时信息,包括哈希码,GC分代年龄,锁状态标志等
数组长度 (数组对象)
无锁
偏向锁 只需比较ThreadID
轻量级锁 自旋 指向栈中锁记录指针
重量级锁 依赖mutex(操作系统互斥) 指向 互斥量 指针
对象监视器 monitor 对象
同步队列 等待队列
_owner 当前持有锁的线程
_EntryList 所有阻塞等待锁的线程
多个线程竞争锁,先进入 EntryList 队列 ,竞争成功的线程标记为 Owner ,其他线程继续在此队列中阻塞等待
如果 Owner 线程执行完了,释放锁,Owner 置空,EntryList 中的线程再次竞争锁
如果 Owner 线程调用 wait() 方法,释放锁并进入 WaitSet 中等待被唤醒
Owner 置空,EntryList 中的线程再次竞争锁
_WaitSet 调用 wait() 方法并未被通知的线程
锁优化
锁消除 逃逸分析
锁粗化
自适应自旋
偏向锁 偏向于第一个持有它的线程
轻量级锁
AQS
AbstractQueuedSynchronizer
常见的锁实现算法 TAS,TTAS ,CLH,MCS,
AQS是CLH的一个变种,CLH适用于SMP数据结构,MCS适用于NUMA结构,
CLH和MCS不同在于,CLH是轮询前驱节点的状态判断前驱节点是否释放锁,
MCS是轮询自身节点状态来判断是否可以获得锁,前驱节点释放锁的时候更新后一节点的状态
Java中的大部分同步类(Lock、Semaphore、ReentrantLock等)都是基于AbstractQueuedSynchronizer(AQS)实现的。
AQS 是一种提供了原子式管理同步状态、阻塞和唤醒线程功能以及队列模型的简单框架
AQS 两个重要成员
state 表示锁状态,volatile 修饰 , CAS 操作 state变量
state 为0表示没有任何线程持有锁,线程持有该锁后将 state 加1,释放时减1
多次持有释放则多次加减 ,可重入
AQS维护两个队列
AQS类维护的CLH队列,用于锁机制的实现
AQS的内部类ConditionObject维护的Condition队列(用于支持线程间的协作,提供await,signal,signalAll方法)
AQS核心思想
如果被请求的共享资源空闲,那么就将当前请求资源的线程设置为有效的工作线程,将共享资源设置为锁定状态
如果共享资源被占用,就需要一定的阻塞等待唤醒机制来保证锁分配
这个机制主要用CLH队列的变体实现,将暂时获取不到锁的线程加入到队列中
CLH算法轮询前驱节点的状态,这样会耗费处理器资源
AQS没有一直轮询,而是用阻塞等待唤醒机制来节省处理器资源
CLH Craig、Landin and Hagersten队列,单向链表,
AQS中的队列是CLH变体的虚拟双向队列(FIFO)
AQS通过将每条请求共享资源的线程封装成一个节点来实现锁的分配
AQS使用volatile的int类型的成员变量来表示同步状态,
通过内置的FIFO队列来完成资源获取的排队工作,通过CAS完成对State值的修改
AQS 在线程竞争锁失败后,把线程信息包装成一个节点,加入同步队列
多个线程同时竞争锁失败,都会加入同步队列,使用CAS方式设置同步队列首尾节点的引用
出队列时,首节点的线程在释放同步状态后,将会唤醒后继节点的线程,
并且后继节点的线程在获取到同步状态后将会将自己设置为首节点
设置首节点是通过获取同步状态成功的线程来完成的
因此设置头结点的方法并不需要使用CAS来保证,因为只有一个线程能获取到同步状态
AQS 提供等待通知机制,用来代替传统的Object的wait notify notifyAll 实现线程间的协作
让某些线程一起等待某个条件(Condition)
只有该条件具备时( 调用 signal signalAll方法),这些等待线程才会被唤醒,重新争夺锁
java线程状态及转换
java死锁实例
ReentrantLock原理
基于 wait 和 notifyAll 实现简单的阻塞队列
基于 ReentrantLock Condition await signalAll 实现简单的阻塞队列
Lock和synchronized的区别
synchronized知识点
AQS要点整理
AQS同步队列与条件队列
The java.util.concurrent Synchronizer Framework 翻译
LockSupport简介
上一篇
下一篇
ReentrantLock原理
基于 wait 和 notifyAll 实现简单的阻塞队列
基于 ReentrantLock Condition await signalAll 实现简单的阻塞队列
java死锁实例
SpringBoot启动过程简介
Springboot2 Tomcat自定义配置