zoukankan      html  css  js  c++  java
  • 简话ReentrantLock的可重入锁概念

        ReentrantLock与synchronized两种锁都具有可重入的特征,实际上是个很简单的概念,但是很多人都是不看源码硬解释,导致问题变得玄乎。今天我就简单的进行一下解释,可重入实际上也就是当前获取到锁执行权限的线程,可以多次调用加锁的过程,而不会影响线程的正常运行。

    一、举个例子

        家里只有一辆车,老大、老二需要使用的时候都要去老爸那儿拿钥匙。

     周一 ,老大:“老爸,给我钥匙我要出去浪”,老爸给了他,后来老二又来要钥匙,老爸说你哥拿走了,明天轮到你。同时记录下“老大获得了汽车”(+1),晚上老大回家报道,老爸消掉记录(-1),汽车空置;

     周二 ,老二:“老爸,给我钥匙我要出去浪”,老爸给了他,后来老大又来要钥匙,老爸说你弟拿走了,明天再来。同时记录下“老二获得了汽车”(+1),晚上老二回家报道,老爸消掉记录(-1),汽车空置;

     他俩只能一人出门一人在家吗?不是的。周三的时候老大老二手拉手一起出去看电影,老大找到老爸,老爸说“可以”,记录下“老大获得了汽车”(+1)。老二跟着找老爸,老爸也说“可以”,同时也做了个记录“老二也在车里”(+1)。晚上老大回家报道,老爸消掉一条记录(-1)。老二跟着报了道,老爸再消一条记录(-1)。汽车空置。但是如果老二先跑去上厕所忘了跟老爸报备,结果汽车仍然被标记占用,那么大家就都用不了了。

      这个例子中,汽车就是我们的锁,老大、老二单独行动就是两个独立的线程,一起行动的话就是一个线程。老爸的记录就是ReentrantLock对象里的 State变量,这个变量是volatile线程共享的。当state=0时,即为资源空置,锁被线程获取后 state将从0 -> 1。当线程中嵌套的内部方法又去请求锁的时候,ReentrantLock会去判断当前线程是否已经获取了锁,如果是,则允许内部方法继续运行,不过此时 state状态要加 1,即从 1 -> 2。ReentrantLock的这个机制就是可重入,如果子方法中还有子方法那么这个值将会从2 -> 3甚至无限大。一个线程重复获取锁的时候,需要成对的去释放锁,将state从n一直减为0,释放资源。少一次释放,资源就被锁死;反过来,那么不可重入就是说当线程已经获得了锁,那么子方法是不允许再写获取锁的逻辑了,否则当前线程也被挂起。

    二、写个测试代码

    /**
     * ReentrantLock 测试
     */
    public class ReentrantLockTest2 {
        public ReentrantLock lock = new ReentrantLock();
        /**
         * 外层方法加锁
         * @throws InterruptedException
         */
        public void test() throws InterruptedException {
            lock.lock();
            try {
                test2();
                // System.out.print("当前锁获得线程:" + Thread.currentThread().getName() + "
    ");
            } catch (Exception e) {
    
            } finally {
                lock.unlock();
            }
        }
        /**
         * 内层方法加锁
         * @throws InterruptedException
         */
        public void test2() throws InterruptedException {
            lock.lock();
            try {
                test();
                System.out.print("当前锁获得线程:" + Thread.currentThread().getName() + "
    ");
            } catch (Exception e) {
    
            } finally {
                lock.unlock();
            }
        }
    
        public static void main(String[] args) throws Exception {
            ReentrantLockTest2 testObj = new ReentrantLockTest2();
            ExecutorService executorService = Executors.newCachedThreadPool();
            for (int i = 0; i < 2; i++) {
                int finalI = i;
                executorService.submit(() -> {
                    try {
                        Thread.currentThread().setName("任务"+ finalI);
                        testObj.test();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                });
            }
        }
    }

    三、看看源码

     

     写在最后

      可重入锁实际上就这么简单,state每重入一次就加1,每释放一次就减1。原理很简单,我个人觉得这么做只是为了减少锁机制的使用难度,使用者只用关注方法是否完成了获取锁与释放锁的逻辑。而不用去管调用链上是否已经有人占据了锁。

  • 相关阅读:
    Realtime crowdsourcing
    maven 常用插件汇总
    fctix
    sencha extjs4 command tools sdk
    首次吃了一颗带奶糖味的消炎药,不知道管用不
    spring mvc3 example
    ubuntu ati driver DO NOT INSTALL recommand driver
    yet another js editor on windows support extjs
    how to use springsource tools suite maven3 on command
    ocr service
  • 原文地址:https://www.cnblogs.com/MrSi/p/13982923.html
Copyright © 2011-2022 走看看