1 前言
这节我们主要讲解下我们平时使用的 Synchronized,它的使用大家应该并不陌生。我们知道 Java 中的锁分为内置锁和显示锁,Synchronized 就是我们的内置锁,内置可以理解为我们只需要标记即可,加锁释放啥的JVM都帮我们做了,那么我们这节就好好来看看这个关键字。
另外我们的版本是:1.8 哈
2 Synchronized 的使用
我们知道锁对象可以是任意的对象,那么关于 Synchronized 的使用大概分三种情况吧:
- 作用于非静态方法:也就是没有 static 修饰的方法,这时我们的锁对象就是当前执行该方法的对象;
- 作用于静态方法:就是 static 修饰的方法,这时我们的锁对象是我们的当前类的 Class 对象;
- 同步代码块:锁对象就是代码块锁的对象;
public class TestSynchronized { private Object obj = new Object(); // 修饰非 static 方法,锁对象为当前对象即this public synchronized void test() { } // 修饰 static 方法,锁对象为当前类 Class public synchronized static void say() { } // 静态代码块,锁对象为 obj public void add(int num) { synchronized (obj) { } } }
3 锁的分类
上节我们在看对象结构的时候,我们看到了对象头中的 Mark Word 中记录着我们锁的信息,我们来回顾下:

其实分类就是为了提效,也算是一种分治思想吧,跟我们平时写业务代码类似,划分场景提高并发甚至每个场景也涉及到切换跟我们这里的锁升级、撤销差不多,那我们就来详细看下每种锁。
3.1 无锁
无锁也可以理解为一种初始状态,就是当我们对象创建出来,我们对象头中的锁信息。那么关于我们创建对象出来,里边的初始所信息又分两种情况:
- 默认不更改任何 JVM 配置的情况下:前4秒内,创建出来的为无锁(001),4秒钟以后的为偏向锁(101)也可以称为匿名偏向,因为它是偏向锁只是线程 id 都是0;
- 修改配置-XX:-UseBiasedLocking:关闭偏向锁,那么创建出来的初始锁都是无锁(001),当第一个线程获取锁的时候,会直接变为轻量级锁;
- 修改配置 -XX:BiasedLockingStartupDelay:修改延迟时间,那么时间内的对象为无锁(001),时间后的为偏向锁(101);
4秒的来源是因为 JVM 启用偏向锁有 4秒 的延迟启动机制,这个可以通过 -XX:BiasedLockingStartupDelay 进行更改,比如 -XX:BiasedLockingStartupDelay=0 即延迟0秒。
我们来运行下看看是不是:
1.8版本哈(1.6以后偏向锁默认开启),我们在不更改任何配置的情况下:

当我们
