jvm-3 锁
ddatsh
基本作用是保护临界区资源不会被多个线程同时访问而受到破坏
通过锁, 可以让多个线程排队, 一个一个地进入临界区访问目标对象, 使目标对象的状态总是保持一致
synchronized 方法和 synchronized 代码块:
public class Test {
public void synchronizedBlock() {
synchronized (this) {
System.out.println("synchronizedMethod");
}
}
public synchronized void synchronizedMethod() {
System.out.println("synchronizedMethod");
}
}
从字节码中,编译器会将同步代码块用 monitorenter
和 monitorexit
包裹
同步方法,通过函数的的 access flags
进行标识,当执行有 synchronized
标识的函数时,最后也会调用 monitorenter
和 monitorexit
基本一样的逻辑
JDK 1.6 前, synchronized 只使用了系统层提供的锁机制,例如 Linux 平台上的 mutex,造成进程间切换的开销,性能并不理想
JDK 1.6 引入两种新型锁机制:偏向锁和轻量级锁,为解决在没有多线程竞争或基本没有竞争的场景下的传统锁性能开销
JVM 根据竞争的强度选用不同的锁实现
,来降低锁的使用开销
JVM 每个对象的对象头,保存对象的系统信息,其中 Mark Word 的部分,是实现锁的关键。它是一个多功能的数据区,可以存放对象的哈希值,对象年龄,指针等数据
一个对象使用了哪种锁实现,谁占用了锁,都记录在这个 Mark Word 中
对象状态 | mark word 存储 |
---|---|
偏向锁(biasable) | 偏向的线程 ID |
轻量级锁(lightweight locked) | 指向线程栈中 Lock Record 的指针 |
重量级锁(inflated) | 指向堆中的 monitor 对象的指针 |