代码实例详解【可重入锁】和【不可重入锁】区别?

本文介绍了多线程环境下锁的概念,以防止脏数据和确保线程安全。重点讨论了可重入锁和不可重入锁的区别。通过代码示例展示了ReentrantLock作为可重入锁的特性,即同一线程可以递归获取锁,避免死锁。同时,通过自定义的不可重入锁实现,解释了当锁不可重入时可能导致的死锁问题。文章最后使用synchronized关键字展示了其内在的可重入性质。
摘要由CSDN通过智能技术生成

首先我们要明白锁的概念,在多线程的场景下,不同的线程一起运行会导致脏数据,为了保证线程安全,这时候便出现了锁的概念,锁可以对代码块,资源,对象上锁,上锁之后,只允许一个线程对其进行操作,其他线程都会进入阻塞状态,这也就是阻塞加锁方法,直到锁释放之后,其他线程才可以获取锁对其操作。

之前文章重点单独介绍过Synchronized和Reentrantlock,不明白的同学可以先看看了解:https://blog.csdn.net/ke1ying/article/details/117419257?spm=1001.2014.3001.5501

这篇文章主要是介绍可重入锁和不可重入锁,在jdk中synchronized和Reentrantlock,都是可重入锁,为了更高效的性能和防止发生死锁。

可重入锁可以理解为:同一个线程下,外层方法上锁之后,内层调用的方法也能正常获取锁。

下面先用代码介绍对【不可重入锁】的理解。

 Lock lock = new ReentrantLock();
    public void testA(){
        try{
            //获取锁之后才能进入业务
            lock.lock();
            //业务处理...
            testB();
        }catch (Exception e){

        }finally {
            lock.unlock();
        }

    }

    private void testB() {
        try{
            //获取锁之后才能进入业务
            lock.lock();
            //业务处理...
        }catch (Exception e){

        }finally {
            lock.unlock();
        }
    }

当testA()方法获取锁之后,在业务里调用testB(),此时因为A的锁未释放,所以B不能获取到锁,这时候B的业务不能正常进行下去,导致A也不能正常释放锁,A和B方法就发生了死锁。这就是不可重入锁。

可重入锁是什么呢?

Jdk中带的基本都是可重入锁,下面就用synchronized实例介绍,在锁住同一个object之后,控制台打印可以看出,threadA调用threadB方法,B和A方法不会发生死锁,业务都能进行下去。

打印为: 


@Log4j2
public class SynchronizedController {

    public static void main(String[] args) {
        new Thread(new ThreadTest()).start();
    }

    static class ThreadTest implements Runnable {

        private final Object obj = new Object();

        private void threadA() {
            synchronized (obj) {
                log.info("threadA正常运行...");
                threadB();
            }
        }

        private void threadB() {
            synchronized (obj) {
                log.info("threadB正常运行...");
            }
        }

        @Override
        public void run() {
            threadA();
        }
    }
}

我们自己可以用synchronized + wait + notify来实现不可重入锁,代码如下:

 /**
     * 用synchronized 和 wait 和 notify来实现不可重入锁
     */
    private boolean flag = false;

    public synchronized void lock() {
        while (flag) {
            //当有其他线程获取锁,则进入wait状态
            try {
                wait();
            } catch (Exception e) {
                
            }
        }
        flag = true;
    }

    public synchronized void unlock() {
        //释放锁,并且随机唤醒一个wait的线程
        flag = false;
        notify();
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

后端从入门到精通

你的鼓励是我最大的动力~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值