synchronized 用于三个地方.
修饰普通方法, 那么线程需要获取对象锁.
修饰静态方法, 那么线程需要获取类锁, 其实就是 Class 对象. 类锁和对象锁之间互不干扰.
修改代码块, 也要获取对象锁.
用于代码块的时候对应 monitorenter 指令和 monitorexit 指令, 表示需要获取 monitor 锁才能够执行这个代码块
用于方法的时候, 方法区方法的 flag 参数中就有一个 ACC_SYNCHRONIZED 标示, 表示线程想要执行这个方法就必须先获取 monitor 锁.
对于 monitor 锁, 每个对象都有一个 monitor 锁. 这个锁在 hotspot 虚拟机中是用 c++ 实现的一个 objectMonitor 对象数据结构, 他维护了两个队列同步队列和等待队列, 有点像 AQS 的两个队列. 多个线程同时要获取这个锁的时候就进入同步队列, 同时通过一个指针指向获取到锁的线程, 同时有个计数器 count 用来做锁重入的计数器. 调用 wait 方法的时候线程进入等待队列.
blog.csdn.net/yinbucheng/article/details/72524482
要了解 synchronized 需要了解对象头的概念.
===java 对象在内存中存了哪三个部分数据? 对象头中存了哪两个信息?
包括对象头, 实例数据, 对齐填充
对象头最重要两个部分: mark word, 类型指针
1.mark word 里面有公共的部分包括 hashcode,GC 分代年龄, 锁状态码表示对象的几种锁状态. 随着锁状态的不同, mark word 会呈现出不同的结构.
偏向锁的时候存的就是获取偏性锁的线程 id
轻量级锁的时候就是指向线程栈锁记录的指针.
比如重量级锁就存了指向对象锁 monitor 的指针, 对象锁 monitor 是 c++ 实现的一种数据结构.
2. 类型指针, 确定对象是什么类的实例.
有哪些锁状态呢?
synchronized 引入锁升级以及不同的锁状态, 目的就是为了减少获取锁和释放锁的性能消耗
=== 对象头中的 mark word 都有哪些个状态? 锁状态码都对应了锁的哪些状态呢?
锁状态有 4 中
01--- 无锁 (是否为偏向锁标志为 0),
偏向锁: mark word 存的是获取锁的线程的 id
00--- 轻量级锁, 保存了指向线程栈锁记录的指针.
10--- 重量级锁, 保存了 monitor 对象的指针
锁可以不断升级, 而且不能回头.
锁升级过程
=== 偏向锁适用条件?
适用于不存在锁竞争的情况下同一个线程反复获取锁的场景.
这个线程获取到偏向锁的时候, mark word 会记录这个线程的 id, 这样同一个线程获取锁就不需要任何处理了, 不需要用 CAS 去获取或者释放锁.
但是存在锁竞争的时候, 其他线程也想要这个锁的时候就变成轻量级锁, markword 的结构也变了.
=== 轻量级锁适用的条件?
适用于线程交替执行同步代码块的情况, 也是不存在锁竞争的前提下.
轻量级锁有指向线程栈中锁记录区的指针. 线程的栈帧中创建 lock record 锁记录区域, 锁记录区也有指针指向 mark word. 他们相互指向.
如果获取轻量级锁失败了, 就会尝试使用自旋锁.
=== 适应性自旋锁?
在线程获取轻量级锁的过程中失败了, 为了避免第一次失败就挂起, 线程就会自旋一定的次数尝试再次获取. 如果还是不能获取到锁就升级成重量级锁.
=== 锁粗化 (lock coarsening)
当涉及到一个线程反复对同一个对象加锁和解锁的操作的时候, 就会将这个过程合并成一个更大范围的加锁和解锁操作.
- public void append(){
- stringBuffer.append("a");
- stringBuffer.append("b");
- stringBuffer.append("c");
- }
会在第一个 append 处加锁, 在最后一次 append 处释放锁.
=== 锁消除适用场景? 禁用锁消除的 JVM 指令?
减少一些不必要的加锁. 一般涉及到方法内局部变量的可以进行锁消除. 比如方法内创建局部变量 stringbuilder 循环一万次 append 一个字符, 这种 append 本身是要加锁的但是这边因为是局部变量其他线程碰不到可以进行锁消除.
- for (int i = 0; i < 100000000; i++) {
- test02.append("abc", "def");
- }
- public void append(String str1, String str2) {
- StringBuffer sb = new StringBuffer();
- sb.append(str1).append(str2);
- }
来源: http://www.bubuko.com/infodetail-2745470.html