锁优化的思路和方法

来源:互联网 发布:笔记本电脑必要软件 编辑:程序博客网 时间:2024/05/22 13:05

参见更好的整理

Java中的锁

代码及虚拟机配置级别锁优化


减少锁持有的时间

这里写图片描述

  • 同步方法细化为同步代码块

减小锁粒度

ConcurrentHashMap实现

这里写图片描述

好处

  • 将大对象拆分为小对象,增大并行度,降低锁竞争。
  • 偏向锁、轻量级锁成功率高。

锁分离

这里写图片描述

  • ReadWriteLock
  • 读写分离,读锁之间不会相互阻塞。
  • 联想forkjoin线程池的工作偷取机制
  • LinkedBlockingQueue实现
    Java并发集合实现原理

锁粗化

这里写图片描述
这里写图片描述

  • 锁的获取释放,也是需要付出一些性能代价的。
  • 针对与那些需要频繁获取锁,释放锁的操作,而且每个操作的持有锁的时间很短。

锁消除

这里写图片描述

  • 基于编译器级别的
  • 对于一些线程安全的对象,比如StringBuilder,如果该对象是线程封闭的,即非逸出对象,那么该对象就是运行在单线程中的,这样它的同步机制会带来性能负担,通过JVM的配置,让编译器自动优化这种代码。

这里写图片描述


虚拟机内的锁优化

偏向锁

对象头

  • 32位
  • 描述对象Hash
  • 锁信息
  • 垃圾回收标志
  • 年龄
  • 偏向锁线程ID
    • 已经分配了该锁的线程
    • 在没有竞争的条件下,获得偏向锁的线程ID,在进入同步代码块的时候不需要进行同步操作。
    • 适用于竞争少的场景。
    • 命令-XX:+UseBiasedLocking 默认是启用的

轻量级锁

  • 快速判断线程是否持该对象的锁。
  • 在线程栈中开辟一块空间作为 锁记录BasicObjectLock
  • 通过CAS操作,尝试将修改共享对象的头信息中的Mark指针,指向栈空间开辟的 锁记录。
  • 如果失败了,进行自旋。
  • 如果自旋失败了,则守护共享对象的锁膨胀为重量级的锁。
  • 同样适用于竞争少的情况下。

自旋锁

  • int i=100 -> while(i--){//空操作}
  • 避免线程挂起。

ThreadLocal源码实现

ThreadLocalMap核心对象

  • key是ThreadLocal实例 value是需要封闭在当前线程中的变量
  • ThreadLocalMap 线程的成员变量
    • 内部Entry[] 数组
    • Entry是继承自弱引用的WeakReference<ThreadLocal>
  • cleanSomeSlots()清理无用对象。

  • 内存泄漏问题

0 0