可重入锁和不可重入锁 & 简单 Code 演示

可重入锁 与 不可重入锁

可重入锁

  • 当线程试图获取自己 已经持有的锁时,会立刻获得这个锁,不用等待,可以理解为这个锁可以继承
  • 在锁对象的内部会维护一个 计数器,每次获取锁时,计数器 +1,释放锁时,计数器 -1,当计数器 = 0,释放锁。
  • 如果没有可重入锁,当已经获取锁的线程 再次获取锁时,就会进入死锁状态。

不可重入锁

  • 与可重入锁对应,即一个线程获取到锁后,当再次获取这个锁时,需要等待这个线程释放锁之后才能获取,很明显发生了 死锁阻塞。

在 java 中,synchronized、ReentrantLock 都是可重入锁。

// 测试 synchronized 的可重入特性
public class ReentrantTest {

    public static void main(String[] args) {
        // 第一次获取锁
        synchronized (ReentrantTest.class){
            while (true){
				// 尝试不断的 获取同一把锁
                synchronized (ReentrantTest.class){
                    System.out.println("ReentrantLock");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

}

结果如下:
在这里插入图片描述
结论:当一个线程获取锁后,当再次获取同一把锁时,会默认已经获取了。


代码简单模拟

  • 模拟不可重入锁
 public class NotReentrantLock{

    private static boolean isLock = false;

    // 加锁
    public synchronized void lock() throws InterruptedException {
        // 判断是否加锁
        while (isLock){
            wait();
        }
        // 锁住当前线程
        isLock = true;
    }

    // 解锁
    public synchronized void unLock(){
        isLock = false;
        notify();
    }
}
public class NotReentrantLockTest {

    private static NotReentrantLock notReentrantLock = new NotReentrantLock();

    public static void main(String[] args) throws InterruptedException {
        notReentrantLock.lock();
        dosomething();
        notReentrantLock.unLock();
    }

    public static void dosomething() throws InterruptedException {
        // 在内层方法中 再次获取锁
        notReentrantLock.lock();
        System.out.println("dosomething...");
        notReentrantLock.unLock();
    }

}

结果会被阻塞
在这里插入图片描述

  • 模拟可重入锁
public class MyReentrantLock{

    // 标识是否加锁
    private boolean isLock = false;
    // 锁计数器,记录加锁的次数
    private int count;
    // 暂存当前持有锁的线程
    private Thread currLockThread;

    // 加锁
    public synchronized void lock() throws InterruptedException {
        Thread currThread = Thread.currentThread();
        // 如果在一个线程内,则不进行阻塞,即可重入
        while (isLock && currLockThread != currThread){
            wait();
        }
        // 加锁次数 ++
        count++;
        isLock = true;
        thread = tep;
    }

    // 解锁
    public synchronized void unLock(){
        if (--count == 0) {
	        isLock = false;
	        thread = null;
	        notify();
        }
    }

    // get set...
    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }
}

public class MyReentrantLockTest {

    private static MyReentrantLock myReentrantLock = new MyReentrantLock();

    public static void main(String[] args) throws InterruptedException {
        myReentrantLock.lock();
        System.out.println(myReentrantLock.getCount());
        dosomething();
        myReentrantLock.unLock();
        System.out.println(myReentrantLock.getCount());
    }

    public static void dosomething() throws InterruptedException {
        // 在内层方法中 再次获取锁
        myReentrantLock.lock();
        System.out.println(myReentrantLock.getCount());
        System.out.println("dosomething...");
        myReentrantLock.unLock();
        System.out.println(myReentrantLock.getCount());
    }

}


代码执行结果如下
在这里插入图片描述

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值