知识整理
- Synchronized 内置锁,JVM级别
- 使用
- 底层 锁升级过程、CAS操作的缺点【替换线程和copy mw】
- 优化
- 代码优化:同步代码块、减少锁粒度、读锁并发
- JDK自带 偏置锁、轻量级锁(CAS操作)、自适应自旋、锁粗化、锁消除
- Volatile
-
- 概念:非阻塞可见性、禁止指令重排序*
- 与syn区别: 无法实现原子操作、使用场景--单线程、不依赖当前值
-
- Reentrantlock 显示锁:基于AQS实现,API级别
- AQS原理:
- 数据结构:state、waitstate【signal-1、传播-3】、
- 独占、共享 tryAcquireShared
- 非公平锁
- 特性锁 可重入、轮询、定时、可中断
- 优点、使用场景
- 与Syn区别、Syn优点
- AQS原理:
- 死锁
- 概念:多个线程因竞争资源而互相等待的僵局;4个必要条件:资源互斥、不可剥夺、保持与请求、循环等待
- 死锁避免:锁顺序、锁时限、死锁检测与恢复
- 死锁检测与恢复:分配资源时不加条件;检测时机:进程等待、定时、利用率下降
- 检测算法:资源分配表、遍历锁关系图
- 撤销进程、设置线程随机优先级
- 锁模式
- 读锁、写锁
- 乐观锁:用户解决---数据版本id、时间戳;CAS;适合写操作少的场景;MVCC实现
- 悲观锁:数据库行锁、页锁...
synchronized的4种应用方式 jvm内部实现 称为:内置锁
synchronized关键字最主要有以下3种应用方式,都是作用在对象上
- 修饰类,作用范围:synchronized括号内, 作用对象:类的所有对象;synchronized(Service.class){ }
- 修改静态方法,作用范围:整个静态方法, 作用对象:类的所有对象;
- 修饰方法,被修饰的同步方法,作用范围:整个方法, 作用对象:调用这个方法的对象;
- 缺点:A线程执行一个长时间任务,B线程必须等待
- 修饰代码块,被修饰的代码块同步语句块,作用范围:大括号内的代码, 作用对象:调用这个代码块的对象;
- 优点:减少锁范围,耗时的代码放外面,可以异步调用
notify 方法实现只唤醒一个线程,由操作
lock.notify()方法最终通过ObjectMonitor的void notify(TRAPS)实现:
1、如果当前_WaitSet【线程等待的集合】为空,即没有正在等待的线程,则直接返回;
2、通过ObjectMonitor::DequeueWaiter 出队方法,获取_WaitSet列表中的第一个ObjectWaiter节点,实现也很简单【选择哪个线程取决于操作系统对多线程管理的实现】
3、根据不同的策略,将取出来的ObjectWaiter节点,加入到Contention List,或自旋操作,CAS改变第一个节点的的指针为新增节点
notifyAll方法实现
lock.notifyAll()方法最终通过ObjectMonitor的void notifyAll(TRAPS)实现:
通过for循环取出_WaitSet的ObjectWaiter节点,并根据不同策略,加入到_EntryList或则进行自旋操作。
从JVM的方法实现中,可以发现:notify和notifyAll并不会释放所占有的ObjectMonitor对象,其实真正释放ObjectMonitor对象的时间点是在执行monitorexit指令,
一旦释放ObjectMonitor对象了,Entryset中ObjectWaiter节点所保存的线程,就可以开始竞争ObjectMonitor对象进行加锁操作了,和ready线程竞争?
2.锁的的实现:内存机制 copy到工作内存-> 修改-> 刷新主存 的过程,才会释放它得到的锁,达到线程安全。
- 锁住(lock)
- 主->从 read load 将需要的数据从主内存拷贝到自己的工作内存(read and load)
- 修改 use assign 根据程序流程读取或者修改相应变量值(use and assign)
- 从->主 store write将自己工作内存中修改了值的变量拷贝回主内存(store and write)
- 释放对象锁(unlock)
线程安全:
- 当多个线程访问某个类,其始终能表现出正确的行为
- 采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,限制其他线程访问,直到锁释放
Java中的锁优化 代码方式、JDK自带方式
1.代码 锁优化
- 减少锁持有时间
- 使用同步代码块,而非同步方法;
- 减小锁粒度
- JDK1.6中 ConcurrentHashMap采取对segment加锁而不是整个map加锁,提高并发性;
- 锁分离 读锁之间不互斥;读写分离
- 根据同步操作的性质,把锁划分为的读锁和写锁,读锁之间不互斥,提高了并发性
2.JDK1.6 锁优化 synchronized底层
1.引入偏向锁、轻量级锁
- 锁主要存在四中状态,依次是:无锁状态01、偏向锁状态01、轻量级锁状态00、重量级锁状态10,
- 会随着竞争的激烈而逐渐升级,锁可以升级不可降级,提高 获得锁和释放锁 效率
- “轻量级锁”和“偏向锁”作用:减少 获得锁和释放锁 的性能消耗
锁 |
优点 |
缺点 |
适用场景 |
偏向锁 |
记录线程iD,若该线程,则不加锁;锁状态01 |
如果线程间存在锁竞争,会带来额外的锁撤销的消耗。 |
适用于只有一个线程访问同步块场景。 |
轻量级锁 </ |