java lock 信号_java各种锁(ReentrantLock,Semaphore,CountDownLatch)的实现原理

先放结论:主要是实现AbstractQueuedSynchronizer中进入和退出函数,控制不同的进入和退出条件,实现适用于各种场景下的锁。

JAVA中对于线程的同步提供了多种锁机制,比较著名的有可重入锁ReentrantLock,信号量机制Semaphore,队列等待机制CountDownLatch,

通过查看源代码可以,他们都是基于AbstractQueuedSynchronizer实现了自身的功能。

796dfedd20df3334c2a5ec4ac5538cdd.png

对于AbstractQueuedSynchronizer的讲解,可以看上一篇文章,这里就讲解下,如何通过集成AbstractQueuedSynchronizer实现上述的锁机制。

所谓的锁实现,就是对AbstractQueuedSynchronizer中state变量的抢占,谁先抢占并且修改了这个变量值不为0,谁就获得了锁。

AbstractQueuedSynchronizer保留了几个未实现的接口供子类实现。分别是

protected boolean tryAcquire(intarg) {throw newUnsupportedOperationException();

}protected boolean tryRelease(intarg) {throw newUnsupportedOperationException();

}protected int tryAcquireShared(intarg) {throw newUnsupportedOperationException();

}protected boolean tryReleaseShared(intarg) {throw newUnsupportedOperationException();

}

tryAcquire和tryRelease是用于独占锁的获取和释放,tryAcquireShared和tryReleaseShared是共享锁的获取和释放,下面看下他们分别是什么地方被调用。

/*** Acquires in exclusive mode, ignoring interrupts. Implemented

* by invoking at least once {@link#tryAcquire},

* returning on success. Otherwise the thread is queued, possibly

* repeatedly blocking and unblocking, invoking {@link* #tryAcquire} until success. This method can be used

* to implement method {@linkLock#lock}.

*

*@paramarg the acquire argument. This value is conveyed to

* {@link#tryAcquire} but is otherwise uninterpreted and

* can represent anything you like.*/

public final void acquire(intarg) {if (!tryAcquire(arg) &&acquireQueued(addWaiter(Node.EXCLUSIVE), arg))

selfInterrupt();

}/*** Releases in exclusive mode. Implemented by unblocking one or

* more threads if {@link#tryRelease} returns true.

* This method can be used to implement method {@linkLock#unlock}.

*

*@paramarg the release argument. This value is conveyed to

* {@link#tryRelease} but is otherwise uninterpreted and

* can represent anything you like.

*@returnthe value returned from {@link#tryRelease}*/

public final boolean release(intarg) {if(tryRelease(arg)) {

Node h=head;if (h != null && h.waitStatus != 0)

unparkSuccessor(h);return true;

}return false;

}/*** Acquires in shared mode, ignoring interrupts. Implemented by

* first invoking at least once {@link#tryAcquireShared},

* returning on success. Otherwise the thread is queued, possibly

* repeatedly blocking and unblocking, invoking {@link* #tryAcquireShared} until success.

*

*@paramarg the acquire argument. This value is conveyed to

* {@link#tryAcquireShared} but is otherwise uninterpreted

* and can represent anything you like.*/

public final void acquireShared(intarg) {if (tryAcquireShared(arg) < 0)

doAcquireShared(arg);

}/*** Releases in shared mode. Implemented by unblocking one or more

* threads if {@link#tryReleaseShared} returns true.

*

*@paramarg the release argument. This value is conveyed to

* {@link#tryReleaseShared} but is otherwise uninterpreted

* and can represent anything you like.

*@returnthe value returned from {@link#tryReleaseShared}*/

public final boolean releaseShared(intarg) {if(tryReleaseShared(arg)) {

doReleaseShared();return true;

}return false;

}

在acquire中,如果tryAcquire失败,那么就去等待队列中排队,release中如果tryRelease成功,那么就唤醒下一个等待队列中的线程。

acquireShared中,如果tryAcquireShared失败,那么再次进入循环获取过程,releaseShared中,如果tryReleaseShared成功,那么就唤醒下一个等待队列中的线程。

现在的主要问题是,如何判定上述的tryAcquire、tryRelease、tryAcquireShared和tryReleaseShared的成功和失败,

通过阅读源代码可知:

ReentrantLock是一个线程执行,其他线程等待。

ReentrantLock的实现机制就是:线程lock()时,获取时state变量的值不为0,那么tryAcquire就失败,tryRelease执行完state变量的值==0,表示成功,唤醒等待的线程,否则就是失败。

Semaphore是先分配一定数量的许可证,然后多个线程来抢许可证,抢到就可以执行。

Semaphore的实现机制就是:如果获取时当前state减去申请的信号量数目acquires>0,那么就表示成功,此时 state=state-acquires, 否则失败,释放时,当前释放的信号量不为负数,那么就表示成功,唤醒等待的线程,释放后state=state+acquires.

CountDownLatch是一个线程执行,其他线程等待。

CountDownLatch的实现机制是: 线程如果lock()时,获取时state变量的值不为0,那么tryAcquire就失败,tryRelease执行完state变量的值等于0或者state-1后值等于0,表示成功,唤醒等待的线程,否则就是失败。

ReentrantLock的代码如下:

final boolean nonfairTryAcquire(intacquires) {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;

}protected final boolean tryRelease(intreleases) {int c = getState() -releases;if (Thread.currentThread() !=getExclusiveOwnerThread())throw newIllegalMonitorStateException();boolean free = false;if (c == 0) {

free= true;

setExclusiveOwnerThread(null);

}

setState(c);returnfree;

}

Semaphore代码如下:

final int nonfairTryAcquireShared(intacquires) {for(;;) {int available =getState();int remaining = available -acquires;if (remaining < 0 ||compareAndSetState(available, remaining))returnremaining;

}

}protected final boolean tryReleaseShared(intreleases) {for(;;) {int current =getState();int next = current +releases;if (next < current) //overflow

throw new Error("Maximum permit count exceeded");if(compareAndSetState(current, next))return true;

}

}

CountDownLatch代码如下:

protected int tryAcquireShared(intacquires) {return (getState() == 0) ? 1 : -1;

}protected boolean tryReleaseShared(intreleases) {//Decrement count; signal when transition to zero

for(;;) {int c =getState();if (c == 0)return false;int nextc = c-1;if(compareAndSetState(c, nextc))return nextc == 0;

}

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/388807.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Intent.ACTION_MAIN

1 Intent.ACTION_MAIN String: android.intent.action.MAIN 标识Activity为一个程序的开始。比较常用。 Input:nothing Output:nothing 例如&#xff1a; 1 <activity android:name".Main"android:label"string/app_name">2 <intent-filter…

足球预测_预测足球热

足球预测By Aditya Pethe通过阿蒂亚皮特(Aditya Pethe) From September to January every year, football takes over America. Games dominate TV Sunday and Monday nights, and my brother tears his hair out each week over his consistently underperforming fantasy te…

C#的特性Attribute

一、什么是特性 特性是用于在运行时传递程序中各种元素&#xff08;比如类、方法、结构、枚举、组件等&#xff09;的行为信息的声明性标签&#xff0c;这个标签可以有多个。您可以通过使用特性向程序添加声明性信息。一个声明性标签是通过放置在它所应用的元素前面的方括号&am…

python3中朴素贝叶斯_贝叶斯统计:Python中从零开始的都会都市

python3中朴素贝叶斯你在这里 (You are here) If you’re reading this, odds are: (1) you’re interested in bayesian statistics but (2) you have no idea how Markov Chain Monte Carlo (MCMC) sampling methods work, and (3) you realize that all but the simplest, t…

【转载】移动端布局概念总结

布局准备工作及布局思想及概念: 一个显示器&#xff08;pc端显示器 及 手机屏显示器&#xff09;&#xff0c;既有物理像素&#xff0c;又有独立像素&#xff08;独立像素也叫作css像素&#xff0c;用于前端人员使用&#xff09;&#xff1b; -->重要 首先确定设计稿的尺寸…

深入浅出:HTTP/2

上篇文章深入浅出&#xff1a;5G和HTTP里给自己挖了一根深坑&#xff0c;说是要写一篇关于HTTP/2的文章&#xff0c;今天来还账了。 本文分为以下几个部分&#xff1a; HTTP/2的背景HTTP/2的特点HTTP/2的协议分析HTTP/2的支持 HTTP/2简介 HTTP/2主要是为了解决现HTTP 1.1性能不…

画了个Android

画了个Android 今晚瞎折腾&#xff0c;闲着没事画了个机器人——android&#xff0c;浪费了一个晚上的时间。画这丫还真不容易&#xff0c;为那些坐标&#xff0c;差点砸了键盘&#xff0c;好在最后画出个有模有样的&#xff0c;心稍安。 下面来看看画这么个机器人需要些什么东…

数据治理 主数据 元数据_我们对数据治理的误解

数据治理 主数据 元数据Data governance is top of mind for many of my customers, particularly in light of GDPR, CCPA, COVID-19, and any number of other acronyms that speak to the increasing importance of data management when it comes to protecting user data.…

提高机器学习质量的想法_如何提高机器学习的数据质量?

提高机器学习质量的想法The ultimate goal of every data scientist or Machine Learning evangelist is to create a better model with higher predictive accuracy. However, in the pursuit of fine-tuning hyperparameters or improving modeling algorithms, data might …

mysql 集群实践_MySQL Cluster集群探索与实践

MySQL集群是一种在无共享架构(SNA&#xff0c;Share Nothing Architecture)系统里应用内存数据库集群的技术。这种无共享的架构可以使得系统使用低廉的硬件获取高的可扩展性。MySQL集群是一种分布式设计&#xff0c;目标是要达到没有任何单点故障点。因此&#xff0c;任何组成部…

matlab散点图折线图_什么是散点图以及何时使用

matlab散点图折线图When you were learning algebra back in high school, you might not have realized that one day you would need to create a scatter plot to demonstrate real-world results.当您在高中学习代数时&#xff0c;您可能没有意识到有一天需要创建一个散点图…

python字符串和List:索引值以 0 为开始值,-1 为从末尾的开始位置;值和位置的区别哦...

String&#xff08;字符串&#xff09;Python中的字符串用单引号 或双引号 " 括起来&#xff0c;同时使用反斜杠 \ 转义特殊字符。 字符串的截取的语法格式如下&#xff1a; 变量[头下标:尾下标]索引值以 0 为开始值&#xff0c;-1 为从末尾的开始位置。[一个是值&#x…

逻辑回归 python_深入研究Python的逻辑回归

逻辑回归 pythonClassification techniques are an essential part of machine learning and data science applications. Approximately 70% of problems in machine learning are classification problems. There are lots of classification problems that are available, b…

spring定时任务(@Scheduled注解)

&#xff08;一&#xff09;在xml里加入task的命名空间 xmlns:task"http://www.springframework.org/schema/task" http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.1.xsd&#xff08;二&#xff09;启用注…

JavaScript是如何工作的:与WebAssembly比较及其使用场景

*摘要&#xff1a;** WebAssembly未来可期。 原文&#xff1a;JavaScript是如何工作的&#xff1a;与WebAssembly比较及其使用场景作者&#xff1a;前端小智Fundebug经授权转载&#xff0c;版权归原作者所有。 这是专门探索 JavaScript及其所构建的组件的系列文章的第6篇。 如果…

Matplotlib中的“ plt”和“ ax”到底是什么?

Indeed, as the most popular and fundamental data visualisation library, Matplotlib is kind of confusing in some perspectives. It is usually to see that someone asking about的确&#xff0c;作为最受欢迎的基础数据可视化库&#xff0c;Matplotlib在某些方面令人困…

2018年阿里云NoSQL数据库大事盘点

2019独角兽企业重金招聘Python工程师标准>>> NoSQL一词最早出现在1998年。2009年Last.fm的Johan Oskarsson发起了一次关于分布式开源数据库的讨论&#xff0c;来自Rackspace的Eric Evans再次提出了NoSQL概念&#xff0c;这时的NoSQL主要是指非关系型、分布式、不提供…

cayenne:用于随机模拟的Python包

TL;DR; We just released v1.0 of cayenne, our Python package for stochastic simulations! Read on to find out if you should model your system as a stochastic process, and why you should try out cayenne.TL; DR; 我们刚刚发布了 cayenne v1.0 &#xff0c;这是我们…

java 如何将word 转换为ftl_使用 freemarker导出word文档

近日需要将人员的基本信息导出&#xff0c;存储为word文档&#xff0c;查阅了很多资料&#xff0c;最后选择了使用freemarker&#xff0c;网上一共有四种方式&#xff0c;效果都一样&#xff0c;选择它呢是因为使用简单&#xff0c;再次记录一下,一个简单的demo&#xff0c;仅供…

DotNetBar office2007效果

1.DataGridView 格式化显示cell里的数据日期等。 进入编辑列&#xff0c;选择要设置的列&#xff0c;DefaultCellStyle里->行为->formart设置 2.tabstrip和mdi窗口的结合使用给MDI窗口加上TabPage。拖动个tabstrip到MDI窗口上tabstrip里选择到主窗口名就加上TABPAGE了。d…