首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

可重入锁和不可重入锁的区别

可重入锁和不可重入锁的主要区别在于它们对同一线程多次获取同一资源时的处理方式。以下是对这两种锁机制的详细解析:

可重入锁

  • 定义:可重入锁,也称为递归锁,允许同一个线程多次获取同一把锁而不会导致死锁。这是通过在锁内部维护一个计数器来实现的,该计数器记录当前线程获取锁的次数。
  • 工作原理:当一个线程已经持有锁并尝试再次获取锁时,可重入锁会允许这种行为,通过递增计数器来跟踪当前线程获取锁的次数。只有当计数器归零时,其他线程才能获取该锁。
  • 优势:可重入锁的主要优势在于其能够避免死锁,提高程序的灵活性和效率。
  • 类型:在Java中,可重入锁的实现包括synchronized关键字和ReentrantLock类。
  • 应用场景:可重入锁广泛应用于需要线程安全的数据结构、递归函数以及任何需要在同一线程中多次访问共享资源的场景。

不可重入锁

  • 定义:不可重入锁指的是如果一个线程已经获取了某个锁,再次尝试获取该锁将会失败,导致死锁。这是因为不可重入锁不会允许计数器超过一定阈值。
  • 工作原理:在尝试获取锁时,如果锁已经被当前线程持有,不可重入锁将阻止线程再次获取锁,导致死锁。
  • 应用场景:不可重入锁的使用场景非常少见,通常不推荐使用,因为它们可能导致程序错误。

代码示例

以下是一个简单的Java代码示例,展示了如何使用ReentrantLock实现可重入锁:

代码语言:txt
复制
import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockExample {
    private final ReentrantLock lock = new ReentrantLock();

    public void methodA() {
        lock.lock();
        try {
            // 临界区代码
        } finally {
            lock.unlock(); // 释放锁
        }
    }

    public void methodB() {
        lock.lock();
        try {
            methodA(); // 递归调用,可重入锁允许这样做而不会死锁
        } finally {
            lock.unlock(); // 释放锁
        }
    }
}

在这个例子中,methodAmethodB都可以安全地多次获取lock对象,而不会导致死锁。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

可重入锁和不可重入锁的区别

不可重入锁示例(同一个线程不可以重入上锁后的代码段) 如下是一个不可重入锁的逻辑过程,会发现执行main方法控制台会打印执行doJob方法前,然后就会一直线程阻塞,不会打印执行doJob方法过程中,原因在于第一次上锁后...这种现象就造成了不可重入锁 public class Count{ MyLock lock = new MyLock(); public static void main(String...notify(); // 接触阻塞 } } 可重入锁示例(同一个线程可以重入上锁的代码段,不同的线程则需要进行阻塞) java的可重入锁有:ReentrantLock...(显式的可重入锁)、synchronized(隐式的可重入锁) 可重入锁诞生的目的就是防止上面不可重入锁的那种情况,导致同一个线程不可重入上锁代码段。...设计可重入锁的示例代码 public class MyReentrantLock { boolean isLocked = false; // 默认没有上锁 Thread

46710

Java不可重入锁和可重入锁理解

最近正在阅读Java ReentrantLock源码,始终对可重入和不可重入概念理解不透彻,进行学习后记录在这里。...wait():阻塞当前线程 notify():唤起被wait()阻塞的线程 不可重入锁 所谓不可重入锁,即若当前线程执行某个方法已经获取了该锁,那么在方法中尝试再次获取锁时,就会获取不到被阻塞。...我们尝试设计一个不可重入锁: ? 使用该锁: ? 当前线程执行print()方法首先获取lock,接下来执行doAdd()方法就无法执行doAdd()中的逻辑,必须先释放锁。...这个例子很好的说明了不可重入锁。 可重入锁 接下来,我们设计一种可重入锁 ? 所谓可重入,意味着线程可以进入它已经拥有的锁的同步代码块儿。...可重入锁的概念和设计思想大体如此,Java中的可重入锁ReentrantLock设计思路也是这样

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

    之前文章重点单独介绍过Synchronized和Reentrantlock,不明白的同学可以先看看了解: currentHashMap的公平锁,可中断响应,限制等待实例 这篇文章主要是介绍可重入锁和不可重入锁...,在jdk中synchronized和Reentrantlock,都是可重入锁,为了更高效的性能和防止发生死锁。...可重入锁可以理解为:同一个线程下,外层方法上锁之后,内层调用的方法也能正常获取锁。 下面先用代码介绍对【不可重入锁】的理解。...这就是不可重入锁。 可重入锁是什么呢?...Jdk中带的基本都是可重入锁,下面就用synchronized实例介绍,在锁住同一个object之后,控制台打印可以看出,threadA调用threadB方法,B和A方法不会发生死锁,业务都能进行下去。

    63420

    Java不可重入锁和可重入锁理解

    大家好,又见面了,我是你们的朋友全栈君。 最近正在阅读Java ReentrantLock源码,始终对可重入和不可重入概念理解不透彻,进行学习后记录在这里。...基础知识 Java多线程的wait()方法和notify()方法 这两个方法是成对出现和使用的,要执行这两个方法,有一个前提就是,当前线程必须获其对象的monitor(俗称“锁”),否则会抛出IllegalMonitorStateException...wait():阻塞当前线程 notify():唤起被wait()阻塞的线程 不可重入锁 所谓不可重入锁,即若当前线程执行某个方法已经获取了该锁,那么在方法中尝试再次获取锁时,就会获取不到被阻塞。...这个例子很好的说明了不可重入锁。...可重入锁的概念和设计思想大体如此,Java中的可重入锁ReentrantLock设计思路也是这样 发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/153238.html

    47310

    可重入锁和自旋锁

    可重入锁 可重入就是说某个线程已经获得某个锁,可以再次获取锁而不会出现死锁。 synchronized和ReentrantLock都是可重入的。...但 ReentrantLock 和 synchronized 不一样,需要手动释放锁,所以使用 ReentrantLock 的时候一定要手动释放锁,并且加锁次数和释放次数要一样。...可重入锁的一个好处是可一定程度避免死锁。 methodA 调用 methodB,如果一个线程调用methodA 已经获取了锁再去调用 methodB 就不需要再次获取锁了,这就是可重入锁的特性。...如果不是可重入锁的话,mehtodB 可能不会被当前线程执行,从而可能造成死锁。...可重入锁和自旋锁的优缺点: 自旋锁的优点在于,因为自旋锁不会引起调用者睡眠,所以不会进行线程调度,CPU时间片轮转等耗时操作。所以如果能在很短的时间内获得锁,自旋锁的效率远高于互斥锁。

    16110

    可重入锁

    使用Java进行多线程开发,使用锁是一个几乎不可避免的问题。今天,就让我们来聊一聊这个基础,但是又特别特别重要的话题。 首先,让我们来看一下,到底什么是锁? 以及,为什么要使用锁?...重入锁的实现原理 重入锁内部实现的主要类如下图: ? 重入锁的核心功能委托给内部类Sync实现,并且根据是否是公平锁有FairSync和NonfairSync两种实现。这是一种典型的策略模式。...但一定要注意,公平锁是有代价的。维持公平竞争是以牺牲系统性能为代价的。如果你愿意承担这个损失,公平锁至少提供了一种普世价值观的实现吧! 那公平锁和非公平锁实现的核心区别在哪里呢?...try { return count; }finally { lock.unlock(); } } } 总结 可重入锁算是多线程的入门级别知识点...重入锁的伴生对象Condition提供了await()和singal()的功能,可以用于线程间消息通信。

    46330

    可重入锁

    使用Java进行多线程开发,使用锁是一个几乎不可避免的问题。今天,就让我们来聊一聊这个基础,但是又特别特别重要的话题。 首先,让我们来看一下,到底什么是锁? 以及,为什么要使用锁?...这就导致读线程只读取了半个数据,在读线程看来,User对象的电话号码是不存在。 为了避免类似的问题,我们就需要使用锁。让写线程在修改对象前,先加锁,然后完成姓名和电话号码的赋值,再释放锁。...如下图所示: 总结 可重入锁算是多线程的入门级别知识点,所以我把他当做多线程系列的第一章节,对于重入锁,我们需要特别知道几点: 对于同一个线程,重入锁允许你反复获得通一把锁...默认情况下,重入锁是非公平的,公平的重入锁性能差于非公平锁 重入锁的内部实现是基于CAS操作的。...重入锁的伴生对象Condition提供了await()和singal()的功能,可以用于线程间消息通信。

    77220

    【并发编程】可重入锁和读写锁

    可重入锁ReentrantLock 何为重入: 重进入是指任意线程在获取到锁之后能够再次获取该锁而不会被锁阻塞 import java.util.concurrent.CopyOnWriteArrayList...lock.unlock(); 功能和synchronized差不多 比synchronized轻量 在使用synchronized的时候 多线程间进行协作工作需要通过wait() notify() 进行配合工作...使用Lock的时候 使用Condition类来等待和通知现场 Condition针对的是具体某一把锁 Lock Condition 的使用: import java.util.concurrent.CopyOnWriteArrayList...线程3 5 对应另一个Condition 线程5唤醒线程3 ReentrantReadWriteLock 读写锁 读写锁ReentrantReadWriteLock 核心是实现读写分离的锁 在高并发访问下...尤其是读多写少 性能远高于重入锁 本质是分成两个锁 读锁和写锁 在读锁下 多个线程可以并发的进行访问 但在写锁的时候 只能一个个的顺序访问 读读共享 写写互斥 读写互斥 上代码: import java.util.concurrent.locks.ReentrantReadWriteLock

    32440

    可重入锁详解(什么是可重入)

    大家好,又见面了,我是你们的朋友全栈君。 可重入锁详解 概述 什么是 “可重入”,可重入就是说某个线程已经获得某个锁,可以再次获取锁而不会出现死锁。...例如 package com.test.reen; // 演示可重入锁是什么意思,可重入,就是可以重复获取相同的锁,synchronized和ReentrantLock都是可重入的 // 可重入降低了编程复杂性...可重入锁有 synchronized ReentrantLock 使用ReentrantLock的注意点 ReentrantLock 和 synchronized 不一样,需要手动释放锁,所以使用 ReentrantLock...的时候一定要手动释放锁,并且加锁次数和释放次数要一样 以下代码演示,加锁和释放次数不一样导致的死锁 package com.test.reen; import java.util.Random; import...稍微改一下,在外层的finally里头释放9次,让加锁和释放次数一样,就没问题了 try { lock.lock(); System.out.println("第1次获取锁,这个锁是:"

    93030

    【多线程】乐观悲观锁、重量级轻量级锁、挂起等待自旋锁、公平非公锁、可重入不可重入锁、读写锁

    锁:非常广义的概念,不是指某个具体的锁,所有的锁都可以往这些策略中套 synchronized:只是市面上五花八门的锁种,其中一种典型的实现,Java 内置的,推荐使用的锁 乐观锁和悲观锁 这两个词不是指某个具体的锁...乐观做的事情少一点 悲观做的事情往往更重量级 站在预测锁冲突的概率是否高 synchronized 是自适应的 重量级锁和轻量级锁 效果和悲观乐观是重叠的,只是站在的角度不一样 重量级锁:加锁的开销比较大...“加锁开销“角度 站在加锁的开销角度 synchronized 也是自适应的 挂起等待锁和自旋锁 挂起等待锁:属于是悲观锁/重量级锁的一种典型实现 自旋锁:乐观锁/轻量级锁的一种典型实现 比如: 你去追你的女神...如需要使用公平锁,就需要做额外的工作 比如引入队列,记录每个线程加锁的顺序 可重入锁和不可重入锁 死锁问题:如果一个线程,针对同一把锁,连续加锁两次,就可能出现死锁,如果把锁设为“可重入”就可以避免死锁了...可重入:是专门的计算机术语,不要写作“可重复”这样的词 可重入锁 会记录当前是哪个线程持有了这把锁 在加锁的时候判定,当前申请锁的线程,是否就是锁的持有者 计数器,记录加锁的次数,从而确定何时真正释放锁

    7910

    关于乐观锁、悲观锁、可重入锁....

    并发编程----乐观锁、悲观锁、可重入锁….. 作为一个Java开发多年的人来说,肯定多多少少熟悉一些锁,或者听过一些锁。今天就来做一个锁相关总结。 ?...在乐观锁与悲观锁的选择上面,主要看下两者的区别以及适用场景就可以了。 响应效率 如果需要非常高的响应速度,建议采用乐观锁方案,成功就执行,不成功就失败,不需要等待其他并发去释放锁。...乐观锁如果有人在你之前更新了,你的更新应当是被拒绝的,可以让用户从新操作。悲观锁则会等待前一个更新完成。这也是区别。...可重入锁 若当前线程执行中已经获取了锁,如果再次获取该锁时,就会获取不到被阻塞。...可重入锁也叫递归锁,指的是同一线程外层函数获得锁之后,内层递归函数仍然有获取该锁的代码,但不受影响。

    51810

    ReentrantLock可重入独占锁详解

    基本用法与synchronized相似,都具备可重入互斥的特性,但拥有更强大的且灵活的锁机制。...这部分可以查看:Java并发包源码学习系列:AQS共享式与独占式获取与释放资源的区别 构造方法 Sync直接继承自AQS,NonfairSync和FairSync继承了Sync,实现了获取锁的公平与非公平策略...在该线程没有释放锁的情况下第二次获取该锁后,状态值设置为2,为可重入次数。 在该线程释放锁时,会尝试使用CAS让state值减1,如果减1后状态值为0,则当前线程释放该锁。...总结 API层面的独占锁:ReentrantLock是底层使用AQS实现的可重入的独占锁,区别于synchronized原生语法层面实现锁语义,ReetrantLock通过lock()和unlock()...state与可重入:AQS的state为0表示当前锁空闲,大于0表示该锁已经被占用,某一时刻只有一个线程可以获取该锁。

    31210

    【多线程】乐观悲观锁、重量级轻量级锁、挂起等待自旋锁、公平非公锁、可重入不可重入锁、读写锁

    乐观锁和悲观锁 这两个词不是指某个具体的锁,而是锁的一种“特性”,描述了“一类” 乐观锁:加锁的时候,假设出现冲突的概率不大 接下来围绕加锁要做的工作就会更少 悲观锁:加锁的时候,假设出现锁冲突的概率很大...” 乐观锁和悲观锁需要做的事情是不同的 乐观做的事情少一点 悲观做的事情往往更重量级 站在预测锁冲突的概率是否高 synchronized 是自适应的 重量级锁和轻量级锁 效果和悲观乐观是重叠的...因为: 乐观和悲观是站在“预估所冲突”角度 重量轻量是站在“加锁开销“角度 站在加锁的开销角度 synchronized 也是自适应的 挂起等待锁和自旋锁 挂起等待锁:属于是悲观锁/重量级锁的一种典型实现...没有做啥额外的操作 如需要使用公平锁,就需要做额外的工作 比如引入队列,记录每个线程加锁的顺序 可重入锁和不可重入锁 死锁问题:如果一个线程,针对同一把锁,连续加锁两次,就可能出现死锁,如果把锁设为“可重入...”就可以避免死锁了 可重入:是专门的计算机术语,不要写作“可重复”这样的词 可重入锁 会记录当前是哪个线程持有了这把锁 在加锁的时候判定,当前申请锁的线程,是否就是锁的持有者 计数器,记录加锁的次数

    10110
    领券