在java1.6之前,synchronized一直都是重量级锁,到了jdk1.6对synchronized进行了优化,引入了偏向锁和轻量级锁。
偏向锁
当一个线程要访问一个对象时,会在这个java对象头中写下自己的threadID,因为偏向锁不会主动释放,所以这个线程下次还要访问这个对象时就比较一下对象头中的threadID,如果是自己的就直接访问,如果不是自己的分两种情况1.如果这个线程已经不存活,就置为无锁。2.如果这个线程还存活,就要看这个线程还用不用,如果还用的话就升级轻量级锁,如果不用了,就置为无锁。
轻量级锁
轻量级锁就是通过CAS将锁对象头中的markword替换成自己栈帧中的锁记录,如果成功了就获取到该锁,如果失败了就存在锁竞争关系,这个时候这个对象就通过CAS在自旋,等待获取锁,但是这样是消耗CPU的。
重量级锁
当自旋的线程达到两个时就升级为重量级锁,除了拥有锁的进程,其他进程都将阻塞。
我们可以在代码中查看锁的状态,分为下面几步:
1.我们先看一下每个状态对应的编码
标志位 | 状态 |
---|---|
001 | 未锁定 |
000 | 轻量级锁定或者叫自旋锁 |
010 | 重量级锁 |
101 | 偏向锁 |
2.然后在pom中引入这个包
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.10</version>
</dependency>
3.然后通过如下方法输出对象头
public class TestLock {
public static void main(String args[]) throws InterruptedException {
Object o = new Object();
System.out.println(ClassLayout.parseInstance(o).toPrintable());
synchronized (o) {
System.out.println(ClassLayout.parseInstance(o).toPrintable());
}
}
}
4.以上代码的输出内容如下所示
因此我们可以知道,第一次输出时是无锁状态,第二次输出时是轻量级锁状态。