Java多线程之ReentrantLock重入锁简介与使用教程
转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6543947.html
我们知道,线程安全问题需要通过线程之间的同步来解决,而同步大多使用syncrhoized关键字,简单方便。但是syncrhoized功能上较单一,为此,concurrent包为我们提供了额外的几种同步控制工具,让我们可以根据不同的同步需求更加灵活地选择同步工具。
一:ReentrantLock(重入锁)
ReentrantLock具有可重入、可中断、可限时申请、可公平获取等特点。
它的使用很简单:1:创建一个reentrantlock对象;2:在需要同步控制的代码块的起始处用 lock.lock() 加锁;3:在退出同步控制块处 lock.unlock() 解锁。
1)可重入
ReentrantLock可以重复获得同一把锁,即:在一个线程中,一个reentrantlock对象可以重复调用 lock() 申请这个锁对象进行加锁。
我们知道。如果一个线程申请同步锁时,如果锁被占用了就会导致阻塞,等待请求的锁释放,若是请求的锁刚好是自己以及在使用的锁呢?难道也要导致阻塞吗?可重入性就是为了解决这个问题,若当前线程请求的锁是自己已获得的锁,则使锁的获取计数器+1而已,不会自己阻塞自己,线程继续照常执行。
但是可重入性也要求了,一个线程请求了多少次同一个锁,那么就要相应地在结束时释放多少次。
lock.lock();
lock.lock();
try
{
i++; }
finally
{
lock.unlock();
lock.unlock();
}
2)可中断
如果有两个线程,一个在lock1.lock()后申请了lock2.lock(),一个在lock2.lock()后申请了lock1.lock(),启动这两个线程。这两个线程都在等待对方释放掉已申请的lock,好让自己获得第二个lock而进行下去,这样的话就会导致死锁。我们知道死锁是由于资源请求存在环路导致的,只要打破这个环路即可让大部分请求得到满足,打破就是我们说的——中断。我们可以通过中断其中一个线程,使其让出所占用的资源(已获得的lock),则另一个线程即可获得两个lock而得以继续进行下去。
reentrantlock的可中断锁是通过 lockInterruptibly() 获取的,而不是普通的 lock()方法。
public static ReentrantLock lock1 = new ReentrantLock();
lock1.lockInterruptibly();
我们怎么知道死锁并解决呢?这需要用到ThreadMXBean(Java虚拟机线程管理接口)中提供的一系列方法,我们可以通过 ManagementFactory .getThreadMXBean();来获得一个线程管理接口的实现类,里面实现了ThreadMXBean中的线程管理方法,罗列如下:
| 方法摘要 | |
|---|---|
ThreadInfo[] |
dumpAllThreads(boolean lockedMonitors, boolean lockedSynchronizers) 返回所有活动线程的线程信息,并带有堆栈跟踪和同步信息。 |
long[] |
findDeadlockedThreads() 查找因为等待获得对象监视器或可拥有同步器而处于死锁状态的线程循环。 |
long[] |
findMonitorDeadlockedThreads() 找到处于死锁状态(等待获取对象监视器)的线程的周期。 |
long[] |
getAllThreadIds() 返回活动线程 ID。 |
long |
getCurrentThreadCpuTime() 返回当前线程的总 CPU 时间(以毫微秒为单位)。 |
long |
getCurrentThreadUserTime() 返回当前线程在用户模式中执行的 CPU 时间(以毫微秒为单位)。 |
int |
getDaemonThreadCount() 返回活动守护线程的当前数目。 |
int |
getPeakThreadCount() 返回自从 Java 虚拟机启动或峰值重置以来峰值活动线程计数。 |
int |
getThreadCount() 返回活动线程的当前数目,包括守护线程和非守护线程。 |
long |
getThreadCpuTime(long id) 返回指定 ID 的线程的总 CPU 时间(以毫微秒为单位)。 |
ThreadInfo |
getThreadInfo(long id) 返回指定 id 的不具有堆栈跟踪的线程的线程信息。 |
ThreadInfo[] |
getThreadInfo(long[] ids) 返回其 ID 在输出数组 ids 中的每个线程的线程信息,这些线程不具有堆栈跟踪。 |
ThreadInfo[] |
getThreadInfo(long[] ids, boolean lockedMonitors, boolean lockedSynchronizers) 返回每个线程的线程信息,线程 ID 位于输入数组 ids 中,带有堆栈跟踪和同步信息。 |
ThreadInfo[] |
getThreadInfo(long[] ids, int maxDepth) 返回其 ID 在输入数组 ids 中的每个线程的线程信息,并带有指定堆栈追踪元素数的堆栈追踪。 |
ThreadInfo |
getThreadInfo(long id, int maxDepth) 返回指定 id 的线程的线程信息,并带有指定堆栈追踪元素数的堆栈追踪。 |
long |
getThreadUserTime(long id) 返回指定 ID 的线程在用户模式中执行的 CPU 时间(以毫微秒为单位)。 |
long |
getTotalStartedThreadCount() 返回自从 Java 虚拟机启动以来创建和启动的线程总数目。 |
boolean |
isCurrentThreadCpuTimeSupported() 测试 Java 虚拟机是否支持当前线程的 CPU 时间测量。 |
boolean |
isObjectMonitorUsageSupported() 测试 Java 虚拟机是否支持使用对象监视器的监视。 |
boolean |
isSynchronizerUsageSupported() 测试 Java 虚拟机是否支持使用可拥有同步器的监视。 |
boolean |
isThreadContentionMonitoringEnabled() 测试是否启用了线程争用监视。 |
boolean |
isThreadContentionMonitoringSupported() 测试 Java 虚拟机是否支持线程争用监视。 |
boolean |
isThreadCpuTimeEnabled() 测试是否启用了线程 CPU 时间测量。 |
boolean |
isThreadCpuTimeSupported() 测试 Java 虚拟机实现是否支持任何线程的 CPU 时间测量。 |
void |
resetPeakThreadCount() 将峰值线程计数重置为当前活动线程的数量。 |
void |
setThreadContentionMonitoringEnabled(boolean enable) 启用或禁用线程争用监视。 |
void |
setThreadCpuTimeEnabled(boolean enable) 启用或禁用线程 CPU 时间测量。 |
从上面我们可以看到,通过ThreadMXBean我们可以获取虚拟机当前运行的所以线程的信息,包括 线程ID、存活的线程、死锁的线程等等信息。
所以,我们可以通过ThreadMXBean获取到由reentrantlock的lockInterruptibly()导致的死锁的随便一个线程的ID,然后通过 线程的interrupt() 方法自动中断自己,就可以使得死锁环中其他线程得以顺利执行。
3)可限时申请锁
reentrantlock对象可以限时申请获得锁,如果在限定时间内没能获取则放弃申请,在没锁的情况下执行代码(此时是不同步进行,线程不安全)。这样就不会由于申请被占用的锁而阻塞线程。
限时申请锁是通过 lock.trylock(num,unit)实现的,unit是时间单元,可以选择秒、分钟、小时、天等,num是数量,指定有多少个时间单元时间用来尝试获得锁。
public static ReentrantLock lock = new ReentrantLock();
lock.tryLock(5, TimeUnit.SECONDS);
4)可公平获取
一般的锁不是公平的,不会说先申请的线程就先获得锁,这样容易使得某一个线程一直处于申请获得锁的状态,即——饥饿。
ReentrantLock可以在创建时通过构造参数指定是不是公平锁,当作为公平锁创建时,申请获得该锁的线程们将严格按照“先申请先获得”的顺序来使用该锁。
public ReentrantLock(boolean fair) public static ReentrantLock fairLock = new ReentrantLock(true);
Java多线程之ReentrantLock重入锁简介与使用教程的更多相关文章
- java并发系列(三)-----ReentrantLock(重入锁)功能详解和应用演示
1. ReentrantLock简介 jdk中独占锁的实现除了使用关键字synchronized外,还可以使用ReentrantLock.虽然在性能上ReentrantLock和synchronize ...
- java高并发系列 - 第12天JUC:ReentrantLock重入锁
java高并发系列 - 第12天JUC:ReentrantLock重入锁 本篇文章开始将juc中常用的一些类,估计会有十来篇. synchronized的局限性 synchronized是java内置 ...
- java并发系列(四)-----源码角度彻底理解ReentrantLock(重入锁)
1.前言 ReentrantLock可以有公平锁和非公平锁的不同实现,只要在构造它的时候传入不同的布尔值,继续跟进下源码我们就能发现,关键在于实例化内部变量sync的方式不同,如下所示: /** * ...
- ReentrantLock(重入锁)以及公平性
ReentrantLock(重入锁)以及公平性 标签(空格分隔): java NIO 如果在绝对时间上,先对锁进行获取的请求一定被先满足,那么这个锁是公平的,反之,是不公平的,也就是说等待时间最长的线 ...
- 从源码角度彻底理解ReentrantLock(重入锁)
目录 1.前言 2.AbstractQueuedSynchronizer介绍 2.1 AQS是构建同步组件的基础 2.2 AQS的内部结构(ReentrantLock的语境下) 3 非公平模式加锁流程 ...
- ReentrantLock(重入锁)的源码解析
转自:从源码角度彻底理解ReentrantLock(重入锁)](https://www.cnblogs.com/takumicx/p/9402021.html)) 公平锁内部是FairSync,非公平 ...
- Java多线程之ReentrantLock与Condition
一.ReentrantLock 1.ReentrantLock简介 ReentrantLock是一个可重入的互斥锁,又被称为“独占锁”.ReentrantLock 类实现了 Lock ,它拥有与 sy ...
- ReentrantLock 重入锁(下)
前沿: ReentrantLock 是java重入锁一种实现,在java中我们通常使用ReentrantLock 和 synchronized来实现锁功能,本篇通过例子来理解下Reentr ...
- java多线程之ReentrantLock
前言 相信学过java的人都知道 synchronized 这个关键词,也知道它用于控制多线程对并发资源的安全访问,兴许,你还用过Lock相关的功能,但你可能从来没有想过java中的锁底层的机制是怎么 ...
随机推荐
- 以绑定的方式来启动service
先说下原理,之前我们的启动service就是用startService来启动的,这是显式启动.启动后我们无法得到service中的数据,也无法知道它执行的状态,如果我们要启动它的activity和它建 ...
- 浅谈volatile与automicInteger
在并发环境中有三个因素需要慎重考量,原子性.可见性.有序性. voatile 保证了有序性(防止指令冲排序)和变量的内存可见性(每次都强制取主存数据),每次取到volatile变量一定是最新的 ...
- WSL(Windows Subsystem for Linux)的安装与使用
有关WSL的介绍这里就不做解释了.另外,本文仅适用于win10 build 16215以及之后的版本,之前的版本可参考官方链接. (可使用“winver”命令查看windows版本号) 安装: 1. ...
- cross validation笔记
preface:做实验少不了交叉验证,平时常用from sklearn.cross_validation import train_test_split,用train_test_split()函数将数 ...
- codeforce 192 div2解题报告
今天大家一起做的div2,怎么说呢,前三题有点坑,好多特判.... A. Cakeminator 题目的意思是说,让你吃掉cake,并且是一行或者一列下去,但是必须没有草莓的存在.这道题目,就是判断一 ...
- 十个 Laravel 5 程序优化技巧
性能一直是 Laravel 框架为人诟病的一个点,所以调优 Laravel 程序算是一个必学的技能. 接下来分享一些开发的最佳实践,还有调优技巧,大家有别的建议也欢迎留言讨论. 这里是简单的列表: 配 ...
- 浅析ARM公司在物联网领域的战略布局(转)
随着ARM芯片的出货量越来越多,自信满满的ARM公司统一软硬件平台的战略和雄心壮志越来越凸显.最初ARM公司仅是出售自己的知识产权(IP核)给各大芯片公司,由于最初ARM公司处于劣势,所以给芯片厂商很 ...
- 强制开启android webview debug模式使用Chrome inspect
强制开启android webview debug模式使用Chrome inspect https://blog.csdn.net/zhulin2609/article/details/5143782 ...
- Eclipse小技巧:收起outline的头文件
- Java归去来第4集:java实战之Eclipse中创建Maven类型的SSM项目
一.前言 如果还不了解剧情,请返回第3集的剧情 Java归去来第3集:Eclipse中给动态模块升级 二.在Eclipse中创建Maven类型的SSM项目 2.1:SSM简介 SSM ...