Java不可重入锁和可重入锁理解[通俗易懂]

Java不可重入锁和可重入锁理解[通俗易懂]最近正在阅读JavaReentrantLock源码,始终对可重入和不可重入概念理解不透彻,进行学习后记录在这里。基础知识Java多线程的wait()方法和notify()方法这两个方法是成对出现和使用的,要执行这两个方法,有一个前提就是,当前线程必须获其对象的monitor(俗称“锁”),否则会抛出IllegalMonitorStateException异常,所以这两个方法必须在同步…

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

最近正在阅读Java ReentrantLock源码,始终对可重入和不可重入概念理解不透彻,进行学习后记录在这里。

基础知识

Java多线程的wait()方法和notify()方法

这两个方法是成对出现和使用的,要执行这两个方法,有一个前提就是,当前线程必须获其对象的monitor(俗称“锁”),否则会抛出IllegalMonitorStateException异常,所以这两个方法必须在同步块代码里面调用。

wait():阻塞当前线程

notify():唤起被wait()阻塞的线程

不可重入锁

所谓不可重入锁,即若当前线程执行某个方法已经获取了该锁,那么在方法中尝试再次获取锁时,就会获取不到被阻塞。我们尝试设计一个不可重入锁:

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设计思路也是这样

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

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

(0)
上一篇 2022年6月26日 下午12:00
下一篇 2022年6月26日 下午12:16


相关推荐

  • linux 如何查看端口被哪个进程占用,如何查看linux端口被哪个进程占用

    linux 如何查看端口被哪个进程占用,如何查看linux端口被哪个进程占用查看 linux 端口被哪个进程占用的方法 首先查看被占用的端口的进程 并查询进程 id 然后根据集成 id 查询进程 并查看进程详情信息 最后查看进行所在目录 操作进程即可 本教程操作环境 redhatenterp 1 DELLG3 电脑 查看 linux 端口被哪个进程占用的方法 1 查询被占用的端口 首先是需要输入命令 查看被占用的端口的进程 netstat tunpl g

    2025年7月23日
    9
  • 【STM32】HAL库 STM32CubeMX教程三—-外部中断(HAL库GPIO讲解)

    【STM32】HAL库 STM32CubeMX教程三—-外部中断(HAL库GPIO讲解)前言上一节我们讲解了STM32CubeMX的基本使用和工程的配置,那么这一节我们正式来学习CubeMX配置STM32的各个外设功能了今天我们会详细的带你学习STM32CubeMX配置外部中断,并且讲解HAL库的GPIO的各种函数,带你学习不一样的STM32如果还没有配置过工程,请参看上一篇博客《STM32CubeMX教程二–基本使用(新建工程点亮LED灯)》那么话不多说,我们开…

    2022年6月11日
    105
  • numpy中的meshgrid函数「建议收藏」

    numpy中的meshgrid函数「建议收藏」numpy官方文档meshgrid函数帮助文档https://docs.scipy.org/doc/numpy/reference/generated/numpy.meshgrid.html meshgrid(*xi,**kwargs)功能:从一个坐标向量中返回一个坐标矩阵 参数:x1,x2…,xn:数组,一维的数组代表网格的坐标。indexing:{‘xy’,…

    2022年6月4日
    32
  • OpenSSL密码库算法笔记——第5.1.2章 椭圆曲线算法集

    OpenSSL密码库算法笔记——第5.1.2章 椭圆曲线算法集在定义椭圆曲线点群时出现了描述曲线所用算法的参数constEC_METHOD*meth,这一节就来看看这个参数有什么用处。椭圆曲线算法集的定义如下。typedefstructec_method_stEC_METHOD;structec_method_st{(具体定义略,详情可参见代码文件ec_lcl.h)};//EC_METHOD在结构体ec…

    2022年7月20日
    18
  • cocos2dx lua热更新_cocos2d js

    cocos2dx lua热更新_cocos2d js下载LuaJit源码并编译成32位和64位下载地址:http://luajit.org/download.html进入LuaJIT-2.1.0-beta3执行如下指令:makesudomakeinstallsudoln-sfluajit-2.1.0-beta3/usr/local/bin/luajitkatichar@192LuaJIT-2.1.0-bet…

    2022年10月6日
    3
  • Java SpringBoot下载文件超时

    Java SpringBoot下载文件超时#端口server.port=9098#server端的socket超时间(毫秒),使用值-1表示没有(即无限)超时,默认值为60000(即60秒)#Tomcat附带的标准server.xml将此值设置为20000(即20秒),除非disableUploadTimeout设置为false,否则在读取请求正文(如果有)时也会使用此超时server.connection-timeout=80000server.disableUploadTimeout=false…

    2025年6月9日
    5

发表回复

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

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