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(竞争的线程)
网友评论