java可重入锁与不可重入锁

java可重入锁与不可重入锁所谓重入锁,指的是以线程为单位,当一个线程获取对象锁之后,这个线程可以再次获取本对象上的锁,而其他的线程是不可以的。synchronized和  ReentrantLock都是可重入锁。可重入锁的意义在于防止死锁。实现原理是通过为每个锁关联一个请求计数器和一个占有它的线程。当计数为0时,认为锁是未被占有的;线程请求一个未被占有的锁时,JVM将记录锁的占有者,并且将请求计数器置为1…

大家好,又见面了,我是你们的朋友全栈君。

所谓重入锁,指的是以线程为单位,当一个线程获取对象锁之后,这个线程可以再次获取本对象上的锁,而其他的线程是不可以的。

synchronized 和   ReentrantLock 都是可重入锁。

可重入锁的意义在于防止死锁。

实现原理是通过为每个锁关联一个请求计数器和一个占有它的线程。当计数为0时,认为锁是未被占有的;线程请求一个未被占有的锁时,JVM将记录锁的占有者,并且将请求计数器置为1 。

如果同一个线程再次请求这个锁,计数将递增;

每次占用线程退出同步块,计数器值将递减。直到计数器为0,锁被释放。

关于父类和子类的锁的重入:子类覆写了父类的synchonized方法,然后调用父类中的方法,此时如果没有重入的锁,那么这段代码将产生死锁(很好理解吧)。

例子:

比如说A类中有个方法public synchronized methodA1(){

        methodA2();

}

而且public synchronized methodA2(){

                    //具体操作

}

也是A类中的同步方法,当当前线程调用A类的对象methodA1同步方法,如果其他线程没有获取A类的对象锁,那么当前线程就获得当前A类对象的锁,然后执行methodA1同步方法,方法体中调用methodA2同步方法,当前线程能够再次获取A类对象的锁,而其他线程是不可以的,这就是可重入锁。

 

代码演示:

不可重入锁:

public class Lock{
    private boolean isLocked = false;
    public synchronized void lock() throws InterruptedException{
        while(isLocked){    
            wait();
        }
        isLocked = true;
    }
    public synchronized void unlock(){
        isLocked = false;
        notify();
    }
}

使用该锁:

public class Count{
    Lock lock = new Lock();
    public void print(){
        lock.lock();
        doAdd();
        lock.unlock();
    }
    public void doAdd(){
        lock.lock();
        //do something
        lock.unlock();
    }
}

当前线程执行print()方法首先获取lock,接下来执行doAdd()方法就无法执行doAdd()中的逻辑,必须先释放锁。这个例子很好的说明了不可重入锁。

可重入锁:

接下来,我们设计一种可重入锁

public class Lock{
    boolean isLocked = false;
    Thread  lockedBy = null;
    int lockedCount = 0;
    public synchronized void lock()
            throws InterruptedException{
        Thread thread = Thread.currentThread();
        while(isLocked && lockedBy != thread){
            wait();
        }
        isLocked = true;
        lockedCount++;
        lockedBy = thread;
    }
    public synchronized void unlock(){
        if(Thread.currentThread() == this.lockedBy){
            lockedCount--;
            if(lockedCount == 0){
                isLocked = false;
                notify();
            }
        }
    }
}

所谓可重入,意味着线程可以进入它已经拥有的锁的同步代码块儿。

我们设计两个线程调用print()方法,第一个线程调用print()方法获取锁,进入lock()方法,由于初始lockedBy是null,所以不会进入while而挂起当前线程,而是是增量lockedCount并记录lockBy为第一个线程。接着第一个线程进入doAdd()方法,由于同一进程,所以不会进入while而挂起,接着增量lockedCount,当第二个线程尝试lock,由于isLocked=true,所以他不会获取该锁,直到第一个线程调用两次unlock()将lockCount递减为0,才将标记为isLocked设置为false。

可重入锁的概念和设计思想大体如此,Java中的可重入锁ReentrantLock设计思路也是这样。

 

synchronized和ReentrantLock 都是可重入锁。ReentrantLock与synchronized比较:

1.前者使用灵活,但是必须手动开启和释放锁

2.前者扩展性好,有时间锁等候(tryLock( )),可中断锁等候(lockInterruptibly( )),锁投票等,适合用于高度竞争锁和多个条件变量的地方

3.前者提供了可轮询的锁请求,可以尝试去获取锁(tryLock( )),如果失败,则会释放已经获得的锁。有完善的错误恢复机制,可以避免死锁的发生。

摘自:JAVA可重入锁与不可重入锁   和   Java不可重入锁和可重入锁理解

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/153277.html原文链接:https://javaforall.net

(0)
上一篇 2022年6月26日 上午10:46
下一篇 2022年6月26日 上午10:46


相关推荐

  • PureMVC解析

    PureMVC解析PureMVC 框架的目标很明确 即把程序分为低耦合的三层 Model View 和 Controller 它们合称为 PureMVC 框架的核心 由 Facade 统一管理 关于它的核心层 我们不需要管太多 只需要记得下面几点就可以了 一 Model 保存对 Proxy 对象的引用 Proxy 负责操作数据模型 与远程服务通信存取数据 二 View 保存对 Mediator 对象的引用 由 Mediator 对象来操作具体的视图组件 ViewComponen 例如 Flex 的 DataGr

    2026年3月19日
    2
  • CA-CFAR代码实现

    CA-CFAR代码实现clearall clc closeall 仿真数据 T 0 25 M 100 tc T M fc 1 tc 一个扫频周期 T 为 250ms M 为每个周期采样点 100 fc 采样频率 N 256 n 1 N 一个相关积累时间 64 fw 10 雷达工作频率 10MHzfb 0 102 sqrt fw bragg 频率

    2025年9月21日
    5
  • 用python3实现粒子群优化算法(PSO)

    用python3实现粒子群优化算法(PSO)粒子群优化算法(ParticleSwarmOptimization,PSO)属于进化算法的一种,是通过模拟鸟群捕食行为设计的。从随机解出发,通过迭代寻找最优解,通过适应度来评价解的品质。设想这样一个场景:一群鸟在随机搜索食物。在这个区域里只有一块食物。所有的鸟都不知道食物在那里。但是他们知道当前的位置离食物还有多远。那么找到食物的最优策略是什么呢。最简单有效的就是搜寻目前离食物最近的鸟的周围区…

    2022年5月24日
    46
  • Java面试之Weblogic 及其它

    Java面试之Weblogic 及其它Java面试之Weblogic 及其它

    2022年4月22日
    44
  • React Hook之useContext的介绍与使用

    React Hook之useContext的介绍与使用React 的 useContext 英语场景 如果需要在组件之间共享状态 可以使用 useContext 现在有俩个组件 Navbar 和 Messages 我们希望它们之间共享状态 divclassName test Navbar Messages 使用方法如下 第一步在它们的父组件上使用 React 的 C divclassName test

    2026年3月17日
    1
  • [精华] kingate代理服务器指南

    [精华] kingate代理服务器指南

    2021年8月19日
    45

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号