Java并发编程之锁重入

重入原理:

  • 每个锁关联一个计数器和一个持有线程。
  • 当线程首次获取锁时,计数器置为1,线程成为锁的持有者。
  • 同一线程每次重入,计数器递增;退出同步代码块时计数器递减。
  • 计数器归零时,锁被释放,其他线程可竞争。

锁重入 就像你进自家大门:

  • 你第一次用钥匙开门(获取锁),进入房间(执行同步代码)。
  • 此时你在房间里又打开卧室门(调用另一个synchronized方法),不需要重新掏钥匙,因为整个房子(对象锁)已经被你独占。
  • 等你从卧室出来(退出内层方法),再退出大门(退出外层方法),锁才完全释放。

public class Home {
    public synchronized void enterFrontDoor() {  // 进大门
        System.out.println("进了大门");
        enterBedroom(); // 直接进卧室,不用重新开锁!
    }

    public synchronized void enterBedroom() {   // 进卧室
        System.out.println("进了卧室");
    }

    public static void main(String[] args) {
        Home home = new Home();
        new Thread(home::enterFrontDoor).start(); // 同一线程畅通无阻
    }
}

关键:

  1. 无需竞态阻塞

    • 同一线程内,外层方法(enterFrontDoor)已经持有了对象锁(Home实例的锁)。
    • 内层方法(enterBedroom)发现锁的持有者是当前线程,直接放行,不会触发线程竞争。
  2. 锁计数器机制

    • JVM为每个锁维护一个计数器:
      • 第一次获取锁(进大门)→ 计数器=1
      • 重入调用内层同步方法(进卧室)→ 计数器+1 → 计数器=2
      • 退出内层方法 → 计数器-1 → 计数器=1
      • 退出外层方法 → 计数器-1 → 计数器=0 → 真正释放锁
    • 只有计数器归零时,其他线程才能竞争锁。
  3. 对比“不可重入锁”

    • 如果锁不可重入,当你在enterFrontDoor中调用enterBedroom时:
      • 外层方法已持有锁,内层方法尝试获取同一把锁 → 死锁!(线程自己卡死自己)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值