相信大家在工作或者面试过程中经常听到重入锁这个概念,或者与关键字 synchrozied 的对比,栈长面试了这么多人,80%的面试者都没有答对或没有答到点上,或者把双重效验锁搞混了,哭笑不得。。
所谓重入锁,指的是以线程为单位,当一个线程获取对象锁之后,这个线程可以再次获取本对象上的锁,而其他的线程是不可以的。
最近正在阅读Java ReentrantLock源码,始终对可重入和不可重入概念理解不透彻,进行学习后记录在这里。
锁作为并发共享数据,保证一致性的工具,在JAVA平台有多种实现(如 synchronized 和 ReentrantLock等等 ) 。这些已经写好提供的锁为我们开发提供了便利,但是锁的具体性质以及类型却很少被提及。本系列文章将分析JAVA下常见的锁名称以及特性,为大家答疑解惑。
在Java中,重入锁(ReentrantLock)和同步锁(Synchronized)都是用于实现线程同步的机制,但它们有一些区别。
第二次调用lock后线程就阻塞了,线程开始等待持有锁的线程放手,然而是它是它就是它。
之前写过java的同学对这个概念应该了如指掌,可重入锁又称为递归锁,是指在同一个线程在外层方法获取锁的时候,在进入该线程的内层方法时会自动获取锁,不会因为之前已经获取过还没释放而阻塞。美团技术团队的一篇关于锁的文章当中针对可重入锁进行了举例:
本来打算写设计模式的,在周六日用了两天的时间全部看了一遍,但是写了一篇之后,发现,写的没有网上的好,感觉大家可能看不懂,所以打算继续写并发编程
在Java并发编程中,根据不同维度来区分锁的话,锁可以分为十五种。ReentranckLock就是其中的多个分类。
很久之前就听说了可重入锁,可重入锁究竟是什么意思,以前是囫囵吞枣的,只要记住ReentrantLock和sychronized是可重入锁就行了,爱咋用咋用,好吧,原谅我的无知,最近对基础查漏补缺,发现竟然对其一问三不知,赶紧预习一波,觉得有必要写一篇博客来讲解,就当做什么都没有发生吧,嘿嘿。。。
前面两篇中分别讲了Synchronized和ReentrantLock。两种方式都能实现同步锁,且也都能解决多线程的并发问题。那么这两个有什么区别呢? 这个也是一个高频的面经题。
使用Java进行多线程开发,使用锁是一个几乎不可避免的问题。今天,就让我们来聊一聊这个基础,但是又特别特别重要的话题。
我们经常需要面对复杂的多线程并发控制问题。在这方面,重入锁(Reentrant Lock)是一个常用的工具,它允许线程在持有锁的情况下再次获取同一个锁,从而避免了死锁等问题。而本文将深入探讨重入锁的其中一种实现方式——Condition,以及如何在实际开发中巧妙地使用它来管理多线程并发。本文将逐步介绍Condition重入锁的搭配类,为您提供详细的代码示例,让您的多线程编程水平更上一层楼。
《[死磕 java同步系列之ReentrantLock源码解析(一)——公平锁、非公平锁]》)
Java提供了种类丰富的锁,每种锁因其特性的不同,在适当的场景下能够展现出非常高的效率。
关键字synchronized的作用是实现进程间的同步。它的工作是对同步的代码加锁,使得每一次,只能有一个线程进入同步块,从而保证线程间的安全性(即同步块每次应该只有一个线程可以执行)。
reentrantLock 也是支持重入的,不过他是需要显示的获取重入锁,并且它还可以支持非公平和公平锁:
在读很多并发文章中,会提及各种各样锁如公平锁,乐观锁等等,这篇文章介绍各种锁的分类。介绍的内容如下:
基本介绍了进程和线程的区别、实现多线程的两种方式、线程安全的概念以及如何使用Synchronized实现线程安全,下边介绍一下关于Synchronized的其他基本特性。
在读很多并发文章中,会提及各种各样锁如公平锁,乐观锁等等,这篇文章介绍各种锁的分类,介绍的内容如下:
上面是很多锁的名词,这些分类并不是全是指锁的状态,有的指锁的特性,有的指锁的设计,下面总结的内容是对每个锁的名词进行一定的解释。
可重入锁是指在同一个线程在外层方法获取锁的时候,在进入内层方法会自动获取锁。 ReentrantLock和synchronized都是可重入锁。可重入锁的一个好处是可一定程度避免死锁。
如下是一个不可重入锁的逻辑过程,会发现执行main方法控制台会打印执行doJob方法前,然后就会一直线程阻塞,不会打印执行doJob方法过程中,原因在于第一次上锁后,由于没有释放锁,因此执行第一次lock后isLocked = true,这个时候调用doJob()内部又一次调用了lock()由于上个线程将isLocked = true,导致再次进入的时候就进入死循环。导致线程无法执行System.out.println("执行doJob方法过程中");这行代码,因此控制台只能打印执行doJob方法前。这种现象就造成了不可重入锁
ReentrantLock是实现底层的Lock接口的可重入锁实现。支持公平锁模式和非公平锁模式。
首先我们这里提到的锁,是把所需要的代码块,资源,或数据锁上,在操作他们的时候只允许一个线程去做操作。最终结果是为了保证cpu计算结果的正确性。
在Java多线程编程中,重入锁(ReentrantLock) 和信号量(Semaphore)是两个极其重要的并发控制工具。相信大部分读者都应该比较熟悉它们的使用(如果不清楚的小伙伴,赶快拿出书本翻阅一下)。
一、公平锁/非公平锁 公平锁是指多个线程按照申请锁的顺序来获取锁。 非公平锁是指多个线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程比先申请的线程优先获取锁。有可能,会造成优先级反转或者饥饿现象。 对于Java ReentrantLock而言,通过构造函数指定该锁是否是公平锁,默认是非公平锁。非公平锁的优点在于吞吐量比公平锁大。 对于Synchronized而言,也是一种非公平锁。由于其并不像ReentrantLock是通过AQS的来实现线程调度,所以并没有任何办法使其变成公平锁。 二、可重入锁
Java中的锁是一种多线程编程中的同步机制,用于控制线程对共享资源的访问,防止并发访问时的数据竞争和死锁问题。通过使用锁机制,可以实现数据的同步访问,确保多个线程安全地访问共享资源,从而提高程序的并发性能。
大家都知道线程是有生命周期,但是彤哥可以认真负责地告诉你网上几乎没有一篇文章讲得是完全正确的。
什么是 “可重入”,可重入就是说某个线程已经获得某个锁,可以再次获取锁而不会出现死锁。例如
CAS操作需要输入两个数值,一个旧值(期望操作前的值)和一个新值,在操作期间先比较下旧值有没有发生变化,如果没有发生变化,才交换成新值,发生了变化则不交换。
sleep和wait到底什么区别 其实这个问题应该这么问——sleep和wait有什么相同点。因为这两个方法除了都能让当前线程暂停执行完,几乎没有其它相同点。 wait方法是Object类的方法,这意味着所有的Java类都可以调用该方法。sleep方法是Thread类的静态方法。 wait是在当前线程持有wait对象锁的情况下,暂时放弃锁,并让出CPU资源,并积极等待其它线程调用同一对象的notify或者notifyAll方法。注意,即使只有一个线程在等待,并且有其它线程调用了notify或者notify
可以看到三个线程a,b,c,同时卖票,线程默认抢占式的,哪个线程比较猛(上图c线程比较猛),就可以获得更多资源。
每个Thread类的示例都代表一个线程,而进程是操作系统级别的多任务,JVM就是运行在一个进程当中的。所以在Java中更多的应该考虑线程。进程的内存是可以被多个线程共享使用的。
根据对同步资源处理策略不同,锁在宏观上分为乐观锁与悲观锁,这只是概念上的一种称呼,Java中并没有具体的实现类叫做乐观锁或者悲观锁。
距离失业已经过去两个月了,这是小帅接到的第四次面试邀请。“回去等通知吧...”,简简单单的六个字,把小帅的心再次打入了冰窖。
其实这个问题应该这么问——sleep和wait有什么相同点。因为这两个方法除了都能让当前线程暂停执行完,几乎没有其它相同点。
最近我又双叒叕写了个BUG,一个线上服务死锁了,不过幸亏是个新服务,没有什么大影响。
单纯的 Redis 分布式锁仍然有些场景不满⾜的,如⼀个⽅法获取到锁后,可能在⽅法内继续调这个⽅法,就获取不到锁了。这时就要把锁改进成可重⼊锁。
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
领取专属 10元无门槛券
手把手带您无忧上云