java并发包中的ReentrantLock如何理解
java并发包中的ReentrantLock如何理解
本篇文章为大家展示了java并发包中的ReentrantLock如何理解,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。
java作为一个流行语言,本身对并发的支持也是很好的,JDK中的concurrent包中有一系列的并发工具来帮助开发者快速构建一个高并发系统,其中就有并发开发中不可或缺的跟锁有关的接口java.util.concurrent.locks.Lock,而该接口一个常用的实现类就是ReenTrantLock,下面将深入分析该锁的实现。
首先该锁有哪些特征呢?
一、可重入:
该锁是可重入锁。什么意思呢?就是当前线程如果已经获取锁定,那么再次获取锁定时会立即获取成功而不是死锁,也就是同一个线程可以多次锁定,在锁定的同时会有一个状态记录,记录当前线程锁定了多少次,在释放的时候每释放一次该状态就会减小1,直至该状态减小为0表示锁已经被该线程释放(所以重复锁定多少次就要重复的释放多少次),那是否可以无限锁定呢?答案是否定的,该状态是一个int类型的值,每次重复锁定都会加1,也就是同一线程最多重复锁定的次数等于int所能表示的最大的正整数。那么如果锁定次数超过了该最大值呢?当锁定次数超过该最大值系统将抛出Error,是的,不是异常,而是Error!!!具体代码如下:
代码中当nextc小于0时说明发生了overflow,此时会抛出Error。
二、不响应中断:
虽然Lock接口的lock()方法是一个可能被阻塞的方法(当其他线程持有锁时当前线程需要阻塞等待),但是该方法在阻塞期间并不会像sleep方法一样响应中断,也就是说如果你在lock()方法阻塞期间使用Thread.interrupt()方法尝试中断线程,该线程不会有任何响应,但是当线程获取到锁后你可以使用Thread.interrupted()方法获取该线程的中断状态,此时将获取到线程的中断状态是true。
三、可超时:
传统的synchronize锁在其他线程取得锁后只能无限等待,一直到其他线程释放锁后该线程成功获取到锁才能往下继续,而Lock的tryLock方法则允许立即响应,即如果获取锁失败则立即返回一个false表示获取锁失败或者等待一段时间获取锁失败后返回一个false,该方法意味着如果用户长时间未获取到锁那么就可以尝试返回并做一些其他处理而不是一直在这里等待获取锁,这在某些场景是很有用的。
在具体细节上该锁内部有两个实现,即公平锁和非公平锁,那么非公平锁相较于公平锁又有哪些不同呢?公平与否体现在哪儿呢?
公平主要体现在尝试获取锁时的操作,公平锁在尝试获取锁的时候会先判断当前是否有其他线程已经在等待了,如果没有才会尝试直接获取锁,否则会加入队列等待前边的线程释放锁后才会尝试获取锁。
而非公平锁则不管当前是否已经有线程在等待,直接尝试获取锁,获取失败才会加入队列等待前边的线程释放锁。
(PS:上述公平锁和非公平锁在直接尝试获取失败后都会再判断当前持有锁的线程是否是本线程,如果是则也会获取成功)
非公平锁尝试获取锁部分代码:
公平锁尝试获取锁部分代码:
由源代码很清楚的可以看出公平锁和非公平锁的区别。
最后,什么时候用Lock什么时候用synchronize呢?
这里推荐如果需要细粒度的锁控制、或者预计并发比较低的时候可以用Lock,否则就应该优先考虑synchronize;在高并发的场景下synchronize性能会优于Lock,而且synchronize的死锁是可以被检测出来的,出现死锁时可以通过监控功能监控到,同时synchronize的性能在最新版本也有了大幅的提升,实际性能并不比Lock低(作者目前使用的1.8,并且使用几个简单场景实际测试过),所以如果不是有以上需求或者有其他特殊需求只有Lock能满足的话,应该优先考虑使用synchronize,不过Lock也给我们提供了很好的思路,也算是一个趋势。至于为什么并发的场景很早就有而Lock只在较新的java中有呢?主要是因为Lock依赖于CAS操作,而CAS原子操作在后来才有了硬件上的支持,所以在硬件支持CAS操作后语言层面上才有了Lock。
Java的特点有哪些
Java的特点有哪些 1.Java语言作为静态面向对象编程语言的代表,实现了面向对象理论,允许程序员以优雅的思维方式进行复杂的编程。 2.Java具有简单性、面向对象、分布式、安全性、平台独立与可移植性、动态性等特点。 3.使用Java可以编写桌面应用程序、Web应用程序、分布式系统和嵌入式系统应用程序等。
上述内容就是java并发包中的ReentrantLock如何理解,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注恰卡编程网行业资讯频道。