无锁、轻量级锁、重量级锁

synchronized

jdk早期的版本,其是重量级锁

原因是:其锁操作是通过 kernel+系统调用来完成

CAS

1、compare and swap 或者  compare and exchange

2、CAS称之为无锁,其实更倾向于自旋锁

3、CAS会产生ABA问题

4、什么是ABA问题

比如:有三个线程:m1、m2、m3

这三个线程都进行对 i 这个变量操作,并且都用CAS算法进行操作,当第一个线程在读取完主存到自己内存后,

其他两个线程对 i 分别 加1 和减1

接下来m1接着继续执行,发现当前主存值和读取到的值,无改变,则进行写成功

5、如何解决ABA问题?

有两种方式:1>jdk为我们提供的 atomic包,这里所有相关的操作都用了CAS算法

  2>可以为这个共同修改的变量加  版本号 来进行控制

6、CAS算法底层实现

java层级的CAS算法,在汇编底层就是用了 compare and exchange来进行操作

底层的汇编不是原子操作

底层怎么实现:lock if mp  来进行操作

7、JOL  =  JAVA object layout

对于java new出来的对象,可以看到 其在内存里的布局,以及锁升级的过程

8、对象在内存中的布局

markword 类型指针 实例数据  对齐

如果前三部分的不能够被8整除,则用对齐方式进行补齐。。。原因是:jvm读取内容到内存当中,是一块、一块读取

markWord占用8个字节,下来的四个字节为 类型指针

9、给一个对象上锁的含义

所谓给对象加锁:其实就是给对象头上的markWord加锁

10、所谓的锁升级的过程

锁状态:无锁态、偏向锁、轻量级锁(自旋锁、无锁)、重量级锁 

在markword里有对应的标记位:00表示轻量级锁、10表示重量级锁、11表示GC标记信息(CMS过程中用到的标记信息)

什么是偏向锁:偏向于某个线程,比如StringBuffer里的方法都是用了sychronized,一般都是某一个线程在使用

不需要经过操作系统,把自己的线程ID记录到markWord里

什么是自旋锁:谁能够持有这把锁,通过CAS,即谁能够把markWord修改成功,谁就持有这把锁

这两个锁不需要经过操作系统,所以效率比较高

如果线程非常多的话,要进行升级锁,即就是重量级锁

重量级锁:就是操作系统会把这些线程塞到队列当中,这样就不需要调用CPU,只有排队到你的时候才去调用CPU

11、轻量级锁在什么时候会升级为重量级锁

jdk1.6之前:有两个条件之一满足就可以

有一个线程的自旋次数超过10次

等待锁的线程数为CPU核数的1/2

jdk1.6之后:自适应自旋

jdk会根据线程运行的情况,来进行升级

12、偏向锁的深入

偏向锁未启动和已启动,可以通过参数来配置  -xx:BiasedLockingStartupDelay = 0(表示启动偏向锁).默认是4S

可以通过java -XX:+PrintFlagsFinal | grep BiasedLocking 来查看偏向锁的设置 

默认偏向锁是打开的

默认延时4S

jvm在启动的时候,偏向锁是不需要启动,因为jvm明确知道很多对象都需要内存空间分配

所以在jvm启动完之后,偏向锁才开始启动

匿名偏向:即就是偏向锁启动之后,不偏向任何对象

偏向锁没有启动时候,有竞争怎么办?则这个时候会直接升级为轻量级锁

分代年龄(10种垃圾回收器),前6种和分代有关系

13、new Object 的时候,对象头的分布关系

14、轻量级锁里有一个 lock record 即  锁重入。。。锁重入:就是同一个锁对象可以多次加锁

15、重量级锁的实现

ObjectMonitor(在C++层面) waitSet(正在等待的线程)  EntryList(竞争的线程)

你可能感兴趣的:(无锁、轻量级锁、重量级锁)