2.25复习总结synchronized流程(面向面试回答)
资源来自网络,总结用来巩固知识以及面试,不做任何商用,仅用作学习交流
1 锁的膨胀过程详细:
synchronized用的锁存在于java对象头里的MarkWord中 锁升级主要依赖于MarkWord中锁标志位
偏向锁:偏向锁的出现主要是针对一个线程多次获取相同的对象
获取:线程尝试将对象头里的偏向锁指向当前线程的ID,修改MarkWord中的线程ID 偏向第一个获得锁对象的锁,用CAS操作进行加锁和解锁(重入的时候不用直接获得锁),获取锁的时候,会在对象头里锁记录当前线程ID, 若出现竞争,则升级为轻量级锁 偏向锁使用的是一种当其他线程竞争是才会释放锁的机制(竞争时,如果当前线程还在执行,则升级为轻量级锁,当前线程继续执行。若当前线程已结束,则获得该锁,继续为偏向锁)
轻量级锁(又叫cas锁):
获取过程:首先在当前线程中创建一个存储空间,用来存储MarkWord中的锁记录,将对象头MarkWord中的信息存到当前线程的的存储空间中,然后将MarkWord中的锁记录改为指向当前线程里锁记录的指针,如果成功,则获得当前锁,如果失败,则进入自旋。 自旋也会消耗CPU资源,当竞争激烈时,则升级为重量级锁
重量级锁
把等待线程都放进等待队列里,内核态调用
锁的粗化
锁原则上是上锁的对象越少越好,但如果一段代码里有大量的锁的获取、释放,会浪费大量的资源,所以就粗化为一个锁,这就是锁的粗化。
锁消除
虚拟机进行编译时,对于一些代码上要求同步,但是被检测到不可能存在竞争的对象进行锁的消除。主要判据是逃逸分析
临时想到随手一写: hashtable是对每个方法加synchronized锁,currenthashmap1.7之前用分段锁(16个) 1.8之后通过在节点加锁(synchronized) 用volital保证读并发
volitile
volatile实现有序性和可见性主要是通过内存屏障。
AQS: 通过虚拟的双向队列实现
重要组件: 信号量。countdownLatch倒计时器 CyclicBarrier循环栅栏
countdownLatch 和循环栅栏的区别 1.countdown计数器只能使用一次 ,循环栅栏计数器可以重置 2.循环栅栏提供了很多其他的方法,比如获取当前阻塞的线程数等 3.Countdown是一个线程等待其他线程完成后,自己再去做其他的事情,循环栅栏是多个线程一起等待,达到一种状态后一起做某件事情。
循环栅栏:等到一定数量到达屏障时在放开执行新的任务
Automatic原子类
Automatic类主要是利用CAS+volatile和native方法来保证原子性,避免了synchornized的高开销。
iterator是线程安全的,自带互斥锁