目录
一. 常见的锁策略:
二. CAS
三.synchronized原理
四. HashTable, HashMap, ConcurrentHashMap 之间的区别:
五. 死锁的成因, 和解决方案:
一. 常见的锁策略:
1.乐观锁 vs 悲观锁:
描述的是两种不同的加锁态度
乐观:预测锁冲突概率不高,因此做的工作简单一点
悲观:---------------------较高,------------------复杂一点
2.读写锁 vs 普通互斥锁:
普通互斥锁:如同synchronized 当两个线程竞争一把锁,会产生等待
读写锁:
加读锁: 多个线程同时读一个变量, 不必加锁
加写锁
读锁,无竞争, 写写,有竞争, 读写,有竞争
读写锁比普通互斥锁少了很多锁竞争,优化了效率
3.重量级锁 vs 轻量级锁:
轻量级锁 : 加锁解锁开销小, 存用户态加锁逻辑,开销小
重量级锁 : ------------------大, 进入内核态-----------,开销大
4.自旋锁 vs 挂起等待锁:
自旋锁: 轻量级锁的一种典型实现, 反复询问当前锁是否就绪 (有一种反复问哥哥能带我打游戏嘛??-哥哥烦死了说不打)
挂起等待锁: 重量级锁
5.公平锁 vs 非公平锁
操作系统默认的锁的调度, 是非公平锁
想要实现公平锁, 需要引入额外的数据结构,要额外的开销
6.可重入锁 vs 不可重入锁
可重入锁: 同一个线程针对同一把锁, 连续加锁两次, 不会死锁
不可重入锁: -------------------------, --会死锁
synchronized的对号入座~
1.既是乐观锁, 也是悲观锁
2. --轻量级,--重量级
3.乐观锁的部分是基于自旋锁实现的,悲观是挂起等待
synchronized是自适应!
初使用, 乐观/轻量/自旋, 锁竞争不激烈.上述状态不变
锁竞争激烈.悲/重/挂
二. CAS
1.简单介绍:
compare and swap 比较并交换
寄存器A的值和内存M的值 进行比较,不相同,啥也不干; 相同, 把B的值和M的值进行交换(不关心B的值)
这是由CPU一条指令,原子完成的->安全&&高效
2.常用的两个场景:
1.实现原子类
2.实现自旋锁
3.CAS 与 ABA 问题:
如何解决ABA带来的问题?
只要有一个记录,能够记录上内存中数据的变化,就可以解决ABA问题
如何记录? 另外搞一个内存, 保存M的 ''修改次数''(版本号)[只增不减] 或者是 ''上次修改时间'' [只增不减]
此时修改操作就是比较 版本号/上次修改时间了
三.synchronized原理
一. 锁升级 / 锁膨胀
1.偏向锁
无竞争--类似懒汉模式~必要的时候在加锁,能不加就不加
2.轻量级锁
有竞争
3.重量级锁
竞争激烈
二. 锁消除
JVM自动判定,发现这个地方的代码, 不必加锁, 如果你写了synchronized 就会自动的把锁去掉
锁消除只是在编译器/JVM有十足的把握的时候才进行的
三. 锁粗化
锁的粒度~ synchronized对应代码块包含多少代码,包含代码少,粒度细,包含代码多,粒度粗
锁粗化,就是把细粒度的加锁 -> 粗粒度的加锁
锁粒度也不是越粗就越好, 太粗不利于多线程并发,有悖用多线程初衷
四. HashTable, HashMap, ConcurrentHashMap 之间的区别:
1.HashMap不安全,HashTable, ConcurrentHashMap安全
2.Hashtable 多线程不推荐-无脑加锁-还只加一把-锁冲突很严重
3.ConcurrentHashMap 多线程时请无脑使用这个~
~解释一下 它进行了优化 :
1).锁粒度的控制
每个哈希桶都有自己的锁, 降低锁冲突概率
2).只给写操作加锁, 读操作不加锁
设计巧妙,不会读到修改到一半的数据 旧的/新的
3).充分利用CAS特性
少加锁
4).对于扩容操作,进行特殊优化
新的存储数据的数组不会一次把旧数组里的所有数据都拿过去,一次搞一点
有点像-写寒假作业-一天写一点,和一支笔一盏灯一个奇迹~
优化核心思路:
尽一切可能, 降低锁冲突的概率
五. 死锁的成因, 和解决方案:
1.必要条件:
1).互斥使用:
锁1被线程1占用,线程2不能用 -- 我上厕所呢~你不能进来上厕所
2).不可抢占:
锁1被线程1占用, 线程2不能抢, 除非线程1主动释放--你不能强行打开我上厕所的门! 除非我出来
3).请求和保持:
线程1拿到锁1之后, 还要锁2 -- 一个房间两个厕所,我把第一个厕所锁上了,然后还要锁第二个厕所...
4).循环等待:
线程1等线程2放锁, 2等3, 3等1--漂亮,死循环~
2.解决:
1).2). 是锁特性 改不了
3). 看代码,但是普适性不高
4). 可以~
i). 约定好加锁的顺序,打破循环等待 ---比如给锁编号,加多把锁,必须先加编号小的
ii).银行家算法
可可爱爱,奇奇怪怪,哦,今天又是努力的一天哎~~~