发编程:可重入锁、不可重入锁、公平锁、非公平锁

并发编程:可重入锁、不可重入锁、公平锁、非公平锁


一、可重入锁(Reentrant Lock)

✅ 概念

同一个线程外层方法获取锁之后,在进入该锁保护的内层方法时,可以再次获得锁,不会被自己阻塞。

📌 特点:

  • 锁维护一个持有线程的引用和重入计数器
  • lock() 一次,计数 +1,unlock() 一次,计数 -1

💻 Java 示例

public class ReentrantExample {
    private final ReentrantLock lock = new ReentrantLock();

    public void outer() {
        lock.lock();
        try {
            System.out.println("Entered outer");
            inner(); // 可重入:这里不会死锁
        } finally {
            lock.unlock();
        }
    }

    public void inner() {
        lock.lock(); // 同一线程再次获得锁
        try {
            System.out.println("Entered inner");
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        new ReentrantExample().outer();
    }
}

🧠 本质:

JDK 提供的 synchronizedReentrantLock 默认就是可重入锁


二、不可重入锁(Non-Reentrant Lock)

❌ 概念

一个线程再次请求自己持有的锁时会被阻塞,容易导致死锁

🧪 示例(自定义一个不可重入锁):

public class NonReentrantLock {
    private boolean isLocked = false;
    private Thread lockedBy = null;

    public synchronized void lock() throws InterruptedException {
        while (isLocked) {
            wait();
        }
        isLocked = true;
        lockedBy = Thread.currentThread();
    }

    public synchronized void unlock() {
        if (Thread.currentThread() == lockedBy) {
            isLocked = false;
            lockedBy = null;
            notify();
        }
    }
}

📌 风险:

public class Test {
    private final NonReentrantLock lock = new NonReentrantLock();

    public void methodA() throws InterruptedException {
        lock.lock();
        System.out.println("methodA");
        methodB(); // 死锁:同线程再次加锁会阻塞
        lock.unlock();
    }

    public void methodB() throws InterruptedException {
        lock.lock(); // 被阻塞
        System.out.println("methodB");
        lock.unlock();
    }
}

三、公平锁(Fair Lock)

✅ 概念

线程获取锁的顺序与它们请求锁的顺序一致,先来先得

🔍 Java 实现

ReentrantLock lock = new ReentrantLock(true); // 公平锁

在这里插入图片描述

📌 特点

  • 所有等待线程会排队
  • 每个线程轮到时才能拿到锁
  • 避免线程饥饿

四、非公平锁(Non-Fair Lock)

❌ 概念

线程在请求锁时,可以插队,如果锁空闲就立即获取,不管有没有其他等待线程。

🔍 Java 实现

ReentrantLock lock = new ReentrantLock(false); // 非公平锁,默认

在这里插入图片描述

📌 特点

  • 性能高,吞吐量大
  • 可能出现饥饿现象
  • 减少线程上下文切换

五、总结

分类可重入锁不可重入锁
定义同一线程可以重复获取已持有的锁同一线程重复获取锁会阻塞自己
例子synchronized, ReentrantLock自定义锁或极简实现
是否阻塞自身
死锁风险
分类公平锁非公平锁
加锁顺序先进先出插队,谁抢到谁执行
实现方式ReentrantLock(true)ReentrantLock(false)
性能较低,避免饥饿较高,但可能造成饥饿
使用场景任务调度敏感、公平性重要性能优先,锁竞争激烈

六、建议使用方式

场景建议使用锁类型
方法嵌套、自调用可重入锁(默认即可)
锁竞争不激烈、性能优先非公平锁(默认)
对延迟和公平性要求高(如限流)公平锁
自定义锁类谨慎,需考虑可重入性
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值