Java代码查看对象头和锁状态
添加Maven
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.9</version>
</dependency>
import org.openjdk.jol.info.ClassLayout;
public class ObjectHeader {
private static myobject myobject = new myobject();
public static void main(String[] args) {
System.out.println("当前MAIN线程开始:" + Thread.currentThread().getName() + "--" + ClassLayout.parseInstance(myobject).toPrintable());
// System.out.println("hashCode:" + Long.toHexString(myobject.hashCode()));
// System.out.println("当前线程:" + Thread.currentThread().getName() + "--" + ClassLayout.parseInstance(myobject).toPrintable());
new Thread(new Runnable() {
@Override
public void run() {
synchronized (myobject) {
System.out.println("当前线程:" + Thread.currentThread().getName() + "--" + ClassLayout.parseInstance(myobject).toPrintable());
}
}
}, "线程1号").start();
new Thread(new Runnable() {
@Override
public void run() {
synchronized (myobject) {
System.out.println("当前线程:" + Thread.currentThread().getName() + "--" + ClassLayout.parseInstance(myobject).toPrintable());
}
}
}, "线程2号").start();
System.out.println("当前MAIN线程结束:" + Thread.currentThread().getName() + "--" + ClassLayout.parseInstance(myobject).toPrintable());
}
static class myobject {
public myobject() {
}
}
}
运行结果
锁粗化过程
无锁:没有资源竞争,所有的线程都能访问并修改同一个资源,但同时只有一个线程能修改成功。
偏向锁:偏向锁是指一段同步代码一直被一个线程所访问,那么该线程会自动获取锁,降低获取锁的代价。一个线程访问同步代码块并获取锁时,会在Mark Word里存储锁偏向的线程ID。在线程进入和退出同步块时不再通过CAS操作来加锁和解锁,而是检测Mark Word里是否存储着指向当前线程的偏向锁。引入偏向锁是为了在无多线程竞争的情况下尽量减少不必要的轻量级锁执行路径,因为轻量级锁的获取及释放依赖多次CAS原子指令,而偏向锁只需要在置换ThreadID的时候依赖一次CAS原子指令即可。
轻量级锁:指当锁是偏向锁的时候,被另外的线程所访问,偏向锁就会升级为轻量级锁,其他线程会通过自旋的形式尝试获取锁,不会阻塞,从而提高性能(比如图上的一号线程对象头的00)。进入同步块的时候,如果同步对象锁状态为无锁状态(锁标志位为“01”状态,是否为偏向锁为“0”),虚拟机首先将在当前线程的栈帧中建立一个名为锁记录(Lock Record)的空间,用于存储锁对象目前的Mark Word的拷贝,然后拷贝对象头中的Mark Word复制到锁记录中。拷贝成功后,虚拟机将使用CAS操作尝试将对象的Mark Word更新为指向Lock Record的指针,并将Lock Record里的owner指针指向对象的Mark Word。如果这个更新动作成功了,那么这个线程就拥有了该对象的锁,并且对象Mark Word的锁标志位设置为“00”,表示此对象处于轻量级锁定状态。如果轻量级锁的更新操作失败了,虚拟机首先会检查对象的Mark Word是否指向当前线程的栈帧,如果是就说明当前线程已经拥有了这个对象的锁,那就可以直接进入同步块继续执行,否则说明多个线程竞争锁。若当前只有一个等待线程,则该线程通过自旋进行等待。但是当自旋超过一定的次数,或者一个线程在持有锁,一个在自旋,又有第三个来访时,轻量级锁升级为重量级锁。
重量级锁:锁标志的状态值变为“10”,此时Mark Word中存储的是指向重量级锁的指针,此时等待锁的线程都会进入阻塞状态