Synchroinzed浅析

预备知识

对象头和锁

每个对象 都有一个对象头,叫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。

锁膨胀

当轻量级锁失败,虚拟机就会使用重量级锁

  1. 废弃BeseObjectLock 备份的对象头信息

  2. 正式启用重量级锁
    2.1 通过inflate()方法进行锁膨胀,目的是获取对象的ObjectMonitor
    2.2 使用enter()方法 进入该锁。

自旋锁

在锁膨胀后,操作系统最后的倔强,希望线程可以进入临界期,而不是被线程挂起,一个方法就是自旋锁。

做法:一个for 循环,在n 个循环后,该线程任没有获取锁,则当前线程挂起。

锁消除

不需要线程安全,当时我们用的一些线程安全的一些工具类, 比说 Vector ,StringBuffer 等等

使用参数 +XXDoEscapeAnalysis 和-XX:+EliminateLocks 开启

锁的优化

减少锁的持有时间

减小锁的粒度

参考currentHashMap的实现。

锁分离

锁粗化

posted @ 2021-01-05 23:41  朝明  阅读(191)  评论(2编辑  收藏  举报