1 使用场景
- 锁静态方法 (锁的对象是Class对象)
- 锁实例方法 (锁的对象是类实例)
- 锁方法体 (手动传入一个锁对象:this/Class/其他实例)
2 最基本的Synchronized锁原理
字节码上解释为通过 Monitor Enter 获取锁对象的Monitor监视器;通过Monitor Exit释放锁。
- Monitor Enter
- Monitor Exit
3 Synchronized 在JMM上的含义
使用Synchronized关键字的作用,能为我们做的事情
3-1 Happens before 规则
- 释放锁 HB 加锁
- 上一个线程执行的临界区代码 HB 下一个线程的临界区代码
3-2 内存语义
- 获取锁的时候,从主内存中进行获取数据
- 释放锁的时候,将数据刷新到主内存
- 隐含通信语义:上一个线程向下一个线程传递数据,隐式通信
4 Synchronized 优化
4-1 优化原因
- 重量级Synchronized实现时将没有获取锁的对象放入阻塞队列中进入了休眠,放弃CPU执行权,从而导致上下文切换和线程的唤醒挂起很耗时,所以Synchronized的效率不高。
4-2 优化基础
-
Java对象头,锁的优化过程主要通过Mark Word的
-
Mark Word 里面的数据
4-3 优化过程
锁的升级过程:无锁状态 --> 偏向锁 --> 轻量级锁 --> 重量级锁
根据锁的竞争情况逐步进行升级,不能降级
4-4 偏向锁
目的:锁大多数情况是由一个线程获取,为了让同一个线程获取锁代价低,引入偏向锁,偏向某个线程,即锁很多情况下是不处于竞争状态的。
JVM参数:-XX:BiasedLockingStartupDelay=0
- 偏向锁加锁
当前为偏向锁,通过CAS操作设置当前的偏向线程
- 偏向锁的释放
当锁出现竞争的时候,就会去尝试释放锁资源
4-5 轻量级锁
4-6 各种锁之间的对比
参考