Java synchronized 死锁解析
1. synchronized 修饰方法
synchronized不仅可以修饰代码块,还可以修饰方法(包括实例方法和静态方法)。
// synchronized 修饰实例方法
synchronized public void increase() {
count++;
}
public void increase1() {
synchronized (this) {
// 使用 this 作为锁对象
count++;
}
}
synchronized public static void increase2() {
count++;
}
public void increase3() {
synchronized (Demo1.class) {
// 通过类对象作为锁
count++;
}
}
当 JVM 加载一个 .class 文件时,会在内存中创建对应的数据结构,即'类对象'。类对象包含了类的属性、名字、类型、权限、类方法、继承关系及实现的接口等信息。
2. synchronized 是一个可重入锁
什么是可重入锁? 一个线程针对同一个对象连续加锁两次不会出现死锁。满足这个要求的锁即为可重入锁。
代码示例:
synchronized (locker) {
synchronized (locker) {
count++;
}
}
理论上,如果第一次加锁后阻塞等待释放,第二次加锁会因锁未释放而卡死。但 synchronized 是可重入的,允许同一线程多次获取同一对象的锁。
原理: 对象头(Object Header)中的 Mark Word 保存了锁状态信息。当一个线程给对象加锁时,对象头会有一个计数器。每加一次锁,计数器 +1;解锁时计数器 -1。只有当计数器减为 0 时,锁才真正被释放。
3. 死锁
3.1 死锁的引入
synchronized 是可重入锁,对同一对象连续加锁不会导致死锁。但在以下情况下会出现死锁:
public static {
();
();
(() -> {
(locker1) {
{
Thread.sleep();
} (InterruptedException e) {
(e);
}
(locker2) {
System.out.println();
}
}
});
(() -> {
(locker2) {
{
Thread.sleep();
} (InterruptedException e) {
(e);
}
(locker1) {
System.out.println();
}
}
});
t1.start();
t2.start();
}




