线程生命周期
阻塞有且仅有syncronnized才会阻塞态,也可以说阻塞是被动进入等待态。
死锁条件
死锁例子
解决方案
1.打破‘争夺资源的顺序’,比如另一个线程先拿锁2再拿锁1
image.png
2.打破’拿到资源不放手‘,比如使用显示锁尝试拿锁
注意最后一句Thread.sleep(3)很重要:1.写在了锁之外 2.避免了活锁发生.
为什么不自己用一个map实现ThreadLocal,官方的ThreadLocal实现原理是什么?
自己实现,依然会出现map的竞争问题,官方的ThreadLocal采用了本地变量副本ThreadLocal避免了竞争问题,提升了性能。
现代CPU的CAS基本原理(乐观锁):比如AtomicInteger类
除非特意设计的测试例子,否则一般情况下乐观锁效率都要高于synchonized的,悲观与乐观锁效率时间对比:
怎么解决ABA问题?jdk里提供的两个解决ABA问题的类有什么区别?
1.加版本号来解决 2.一个只能识别有没有改过,另一个能识别改了多少次
线程池
AQS实现原理:
1.内部有一个关键字段state来保存同步状态
2.采用模版设计模式可以让你轻松的实现自己的同步工具类
3.AQS内部本质上是CLH队列锁,即基于链表的自旋锁,每一个需要拿锁的线程打包成一个Node,挂到一个链表上去,每个线程会自旋(大概2次就阻塞)的去检测它前一个节点的线程是不是有没有释放锁,如过释放了,当前线程就拿到锁,并设置排他属性值
ReentrantLock 是如何实现重入锁?是如何实现公平和非公平的?
1.加锁时state ++ ,释放锁时 state -- 直到为0
2.加锁时是否判断了有锁队列
JMM java内存模型:
1.分工作内存和主内存,线程不允许直接操作主内存,线程之间也不予许相互操作
2.volatile 实现原理:
只能保证可见性(意思原先是互不知道对方对临界资源进行了修改),只适用于1.单个变量赋值操作 2用单个线程读多个线程读 3临界值的读写跟多线程前后无关联
1.可以强迫从主内存中读取一次
2.修改完强制刷新到主内存
流水线和抑制重排序:数据读到高速缓存,cpu一次性是可以执行多条指令的
例子:不是说一定要等到if条件了才执行t=b,t=b可能早就执行了放在了重排序缓存区。