预备知识
对象头和锁
每个对象 都有一个对象头,叫Mark Word。它在32位系统中就是32位,在64位操作系统就是64位。
作用
可以存储对象的哈希值,对象年龄,
锁的指针信息(2bit)
ptr 00 # 轻量级锁----自旋
0 01 # 未锁定
1 01 # 偏向锁 -----比较线程ID
ptr 10 # 重量级锁----操作系统
11 # 可GC ------用于标记GC
实现与优化
偏向锁
某一锁被线程获取后,就会进入到偏向模式,当线程再次请求这个线程时,重入,如果有其他线程进行了锁请求,则退出偏向模式。
使用 -XX:UseBiasedLocking 可以设置启用偏向锁。默认开启
轻量级锁
BasicObjectLock 的对象实现。 这个对象放在Java 栈的栈帧中,内部由BasicLock 和一个持有该锁的java对象指针
维护displaced_header 字段,用于备份 对象头的Mark_word。
锁膨胀
当轻量级锁失败,虚拟机就会使用重量级锁
-
废弃BeseObjectLock 备份的对象头信息
-
正式启用重量级锁
2.1 通过inflate()方法进行锁膨胀,目的是获取对象的ObjectMonitor
2.2 使用enter()方法 进入该锁。
自旋锁
在锁膨胀后,操作系统最后的倔强,希望线程可以进入临界期,而不是被线程挂起,一个方法就是自旋锁。
做法:一个for 循环,在n 个循环后,该线程任没有获取锁,则当前线程挂起。
锁消除
不需要线程安全,当时我们用的一些线程安全的一些工具类, 比说 Vector ,StringBuffer 等等
使用参数 +XXDoEscapeAnalysis 和-XX:+EliminateLocks 开启
锁的优化
减少锁的持有时间
减小锁的粒度
参考currentHashMap的实现。