ReentrantLock的实现语义与使用场景
简介
ReentrantLock(重入锁)就是支持可重进入的锁,它表示该锁能支持一个线程对资源的重复加锁。另外还支持获取锁的公平和非公平选择ReentrantLock的实现不仅可以替代隐式的synchronized关键字,而且还能够提供超过关键字本身的多种功能。
公平与非公平
这个概念是针对锁的获取的,在绝对时间上,先对锁进行获取的请求一定先满足,那么这个锁是公平的,反之就是不公平的。公平锁的获取就是等待时间最长的线程最先获取锁,也就是锁获取是顺序的。但是公平锁的机制往往效率不高。
ReentrantLock的调用过程
ReentrantLock把所有Lock接口的操作都委派到一个sync类上,该类继承了队列同步器:
static abstract class Sync extends AbstractQueuedSynchronizer {
final static class NonfairSync extends Sync
final static class FairSync extends Sync
1、sync有两个子类,分别实现的是公平锁和非公平锁,默认为非公平锁。
2、由于该同步组件的实现使用的模板方法模式,我们看下ReentrantLock.lock()方法的调用过程(默认为非公平锁)
非公平锁语义
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
1、首先判断锁当前的状态,如果锁空闲,则当前线程尝试获取。
2、当前线程获取锁成功,则设置当前线程为锁的拥有者。
3、如果锁状态为非空闲状态且当前线程为锁的拥有者,则直接将同步状态值进行增加并返回true,表示获取同步状态成功。
这里就是支持锁重入的场景,跟synchronized类似:成功获取锁的线程再次获取锁,只是增加了同步状态值,与此对应的是,在释放锁的时候需要对应减少同步状态值,直到同步状态值为0的时候,才表示这把锁真正的被释放了。
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
公平锁语义
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (isFirst(current) &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
这里与非公平锁大部分地方类似,只是线程在获取同步状态时,需要判断当前节点的前驱节点是否为首节点。公平锁总是按照队列的顺序来来获取锁的。
ReentrantLock的使用场景
1、发现该操作已经在执行中则不再执行
a、用在定时任务时,如果任务执行时间可能超过下次计划执行时间,确保该任务只有一个正在执行,忽略重复触发。
b、用在界面交互时点击执行较长时间请求操作时,防止多次点击导致后台重复执行。
主要用于进行非重要任务时防止重复执行。
private ReentrantLock lock = new ReentrantLock();
public void test()
{
if(lock.tryLock())
{
try
{
//dosomothing
}
finally
{
lock.unlock();
}
}
}
2、如果该操作已经在执行,则等待一个个执行(同步执行,与synchronized类似)
3、如果该操作已经在执行,则尝试等待一段时间,超时则放弃执行
if(lock.tryLock(5, TimeUnit.SECONDS))
{
try
{
//dosomothing
}
finally
{
lock.unlock();
}
}
这种其实属于场景2的改进,等待获得锁的操作有一个时间的限制,如果超时则放弃执行。
用来防止由于资源处理不当长时间占用导致死锁情况(大家都在等待资源,导致线程队列溢出)。
场景4:如果发现该操作已经在执行,等待执行。这时可中断正在进行的操作立刻释放锁继续下一操作。
synchronized与Lock在默认情况下是不会响应中断(interrupt)操作,会继续执行完。lockInterruptibly()提供了可中断锁来解决此问题。(场景2的另一种改进,没有超时,只能等待中断或执行完毕)
ReentrantLock的实现语义与使用场景的更多相关文章
- 灵魂代码分享HTML元素标签语义化及使用场景实用到爆
灵魂三问: 标签语义化是什么?为什么要标签语义化?标签语义化使用场景有哪些? 下面让我们跟着这三个问题来展开一下本文的内容. 一.标签语义化是什么? 标签语义化就是让元素标签做适当的事情.例如 p 标 ...
- ECCV 2018 | 旷视科技提出统一感知解析网络UPerNet,优化场景理解
全球计算机视觉三大顶会之一 ECCV 2018(European Conference on Computer Vision)即将于 9 月 8 -14 日在德国慕尼黑拉开帷幕.届时,旷视首席科学家孙 ...
- CVPR2020:4D点云语义分割网络(SpSequenceNet)
CVPR2020:4D点云语义分割网络(SpSequenceNet) SpSequenceNet: Semantic Segmentation Network on 4D Point Clouds 论 ...
- PyTorch中的MIT ADE20K数据集的语义分割
PyTorch中的MIT ADE20K数据集的语义分割 代码地址:https://github.com/CSAILVision/semantic-segmentation-pytorch Semant ...
- ReentrantLock可重入锁——源码详解
开始这篇博客之前,博主默认大家都是看过AQS源码的~什么居然没看过猛戳下方 全网最详细的AbstractQueuedSynchronizer(AQS)源码剖析(一)AQS基础 全网最详细的Abstra ...
- 快进来!花几分钟看一下 ReentrantReadWriteLock 的原理!
前言 在看完 ReentrantLock 之后,在高并发场景下 ReentrantLock 已经足够使用,但是因为 ReentrantLock 是独占锁,同时只有一个线程可以获取该锁,而很多应用场景都 ...
- Java并发包源码学习系列:阻塞队列BlockingQueue及实现原理分析
目录 本篇要点 什么是阻塞队列 阻塞队列提供的方法 阻塞队列的七种实现 TransferQueue和BlockingQueue的区别 1.ArrayBlockingQueue 2.LinkedBloc ...
- LMAX Disruptor—多生产者多消费者中,消息复制分发的高性能实现
解决的问题 当我们有多个消息的生产者线程,一个消费者线程时,他们之间如何进行高并发.线程安全的协调? 很简单,用一个队列. 当我们有多个消息的生产者线程,多个消费者线程,并且每一条消息需要被所有的消费 ...
- Fully Convolutional Networks for semantic Segmentation(深度学习经典论文翻译)
摘要 卷积网络在特征分层领域是非常强大的视觉模型.我们证明了经过端到端.像素到像素训练的卷积网络超过语义分割中最先进的技术.我们的核心观点是建立"全卷积"网络,输入任意尺寸,经过有 ...
随机推荐
- JS性能优化笔记搜索整理
通过网上查找资料了解关于性能优化方面的内容,现简单整理,仅供大家在优化的过程中参考使用,如有什么问题请及时提出,再做出相应的补充修改. 一. 让代码简洁:一些简略的表达方式也会产生很好的优化 eg:x ...
- 《深入浅出Windows 10通用应用开发》
<深入浅出Windows 10通用应用开发>采用Windows 10的SDK进行重新改版,整合了<深入浅出Windows Phone 8.1应用开发>和<深入解析 ...
- background常用属性
background-image:url('图片位置');//设置背景图片的位置 background-repeat:no-repeat;//图片是否重复显示(不重复) background-posi ...
- 20161004 NOIP 模拟赛 T1 解题报告
第1题 小麦亩产一千八 [问题描述] “有了金坷垃,肥料一袋能顶两袋撒,小麦亩产一千八,吸收两米下的氮磷钾……”,话说HYSBZ(Hengyang School for Boys & Zy) ...
- 【POJ】3678 Katu Puzzle
http://poj.org/problem?id=3678 题意:很幼稚的题目直接看英文题面= = #include <cstdio> #include <cstring> ...
- MongoDB数据库的简介及安装
一.MongoDB数据库简介 简介 MongoDB是一个高性能,开源,无模式的,基于分布式文件存储的文档型数据库,由C++语言编写,其名称来源取自“humongous”,是一种开源的文档数据库──No ...
- RestTemplate实践
什么是RestTemplate? RestTemplate是Spring提供的用于访问Rest服务的客户端,RestTemplate提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效 ...
- php by oneself
在php里面写html代码真的很麻烦,最近学到了一个新的方法: <html> <head> <title>PHP</title> <meta ht ...
- ckedit 文本编辑器
Ckeditor是一个功能非常强大的富文本编辑器,博客园有使用此编辑器,其功能完全可以与MS的Word媲美. 用起来也非常方便.下面是本人总结的安装步骤: 第一步,从http://ckeditor.c ...
- android-数据存储之外部file存储(sdcard)
一.基础概要 1.说明: 1>应用程序运行用到的数据文件可以保存到sd卡中 2>文件类型:任意 3>数据保存路径: 路径1:/storage/sdcard/Android/data/ ...