重入锁--ReentrantLock
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); // 是当前线程占用,把同步状态数值累加(实际上多数是+1)
return true;
}
return false;
}
protected final boolean tryRelease(int releases) {
int c = getState() - releases; // 每退出一层,就减去相应的数字
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) { //同步状态变为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 (!hasQueuedPredecessors() && 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;
}
public class FairAndUnfairTest {
private static Lock fairLock = new ReentrantLock2(true);
private static Lock unfairLock = new ReentrantLock2(false);
@Test
public void fair() throws Exception {
System.out.println("公平锁");
testLock(fairLock);
}
@Test
public void unfair() throws Exception {
System.out.println("非公平锁");
testLock(unfairLock);
}
public void testLock(Lock lock) throws Exception {
new Thread(new Runnable() {
@Override
public void run() {
for(int i=1; i<6; i++){
Thread thread = new Job(lock);
thread.setName(""+i+"");
thread.start();
mySleep(500);
}
}
}).start();
Thread.sleep(500);
new Thread(new Runnable() {
@Override
public void run() {
for(int i=6; i<11; i++){
Thread thread = new Job(lock);
thread.setName(""+i+"");
thread.start();
mySleep(500);
}
}
}).start();
Thread.sleep(11000);
}
private static class Job extends Thread{
private Lock lock;
public Job(Lock lock){
this.lock = lock;
}
public void run(){
for(int i=0; i<2; i++){
lock.lock();
try {
Thread.sleep(500);
System.out.println("lock by [" + Thread.currentThread().getName() + "], waiting by " + ((ReentrantLock2)lock).getQueuedThread());
} catch (InterruptedException e) {
e.printStackTrace();
}
lock.unlock();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static class ReentrantLock2 extends ReentrantLock{
public ReentrantLock2(boolean fair){
super(fair);
}
public Collection<String> getQueuedThread(){
List<Thread> arrayList = new ArrayList<Thread>(super.getQueuedThreads());
Collections.reverse(arrayList);
List<String> list = new ArrayList<>();
for(Thread thread:arrayList){
list.add(thread.getName());
}
return list;
}
}
private void mySleep(int time){
try {
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}



重入锁--ReentrantLock的更多相关文章
- synchronized关键字,Lock接口以及可重入锁ReentrantLock
多线程环境下,必须考虑线程同步的问题,这是因为多个线程同时访问变量或者资源时会有线程争用,比如A线程读取了一个变量,B线程也读取了这个变量,然后他们同时对这个变量做了修改,写回到内存中,由于是同时做修 ...
- Java 重入锁 ReentrantLock 原理分析
1.简介 可重入锁ReentrantLock自 JDK 1.5 被引入,功能上与synchronized关键字类似.所谓的可重入是指,线程可对同一把锁进行重复加锁,而不会被阻塞住,这样可避免死锁的产生 ...
- 轻松学习java可重入锁(ReentrantLock)的实现原理
转载自https://blog.csdn.net/yanyan19880509/article/details/52345422,(做了一些补充) 前言 相信学过java的人都知道 synchroni ...
- java 可重入锁ReentrantLock的介绍
一个小例子帮助理解(我们常用的synchronized也是可重入锁) 话说从前有一个村子,在这个村子中有一口水井,家家户户都需要到这口井里打水喝.由于井水有限,大家只能依次打水.为了实现家家有水喝,户 ...
- 轻松学习java可重入锁(ReentrantLock)的实现原理(转 图解)
前言 相信学过java的人都知道 synchronized 这个关键词,也知道它用于控制多线程对并发资源的安全访问,兴许,你还用过Lock相关的功能,但你可能从来没有想过java中的锁底层的机制是怎么 ...
- 17_重入锁ReentrantLock
[概述] 重入锁可以完全代替synchronized关键字. 与synchronized相比,重入锁ReentrantLock有着显示的操作过程,即开发人员必须手动指定何时加锁,何时释放锁,所以重入锁 ...
- Java 显示锁 之 重入锁 ReentrantLock(七)
ReentrantLock 重入锁简介 重入锁 ReentrantLock,顾名思义,就是支持同一个线程对资源的重复加锁.另外,该锁还支持获取锁时的公平与非公平性的选择. 重入锁 ReentrantL ...
- Java中可重入锁ReentrantLock原理剖析
本文由码农网 – 吴极心原创,转载请看清文末的转载要求,欢迎参与我们的付费投稿计划! 一. 概述 本文首先介绍Lock接口.ReentrantLock的类层次结构以及锁功能模板类AbstractQue ...
- Java多线程——深入重入锁ReentrantLock
简述 ReentrantLock 是一个可重入的互斥(/独占)锁,又称为“独占锁”. ReentrantLock通过自定义队列同步器(AQS-AbstractQueuedSychronized,是实现 ...
- java线程的同步控制--重入锁ReentrantLock
我们常用的synchronized关键字是一种最简单的线程同步控制方法,它决定了一个线程是否可以访问临界区资源.同时Object.wait() 和Object.notify()方法起到了线程等待和通知 ...
随机推荐
- DPF.Android.Native.Components.v2.8.1 for delphi xe6 使用DPFJAlertDialog遇到的问题
使用DPFJAlertDialog控件时发现DPFJAlertDialog1Click不能捕获到对话框到底按了那个按键,上网搜索后找到了解决方法: 打开DPF.Android.JAlertDialog ...
- Xcode更新至IOS 9 后错误处理
1.obtain an updated library from the vendor, or disable bitcode for this target. for architecture ar ...
- WP REST API: 设置和使用OAuth 1.0a Authentication(原文)
In the previous part of the series, we set up basic HTTP authentication on the server by installing ...
- 数据库索引与b+树
数据库索引详解 索引 当我们在设计数据库的时候,对表的一些属性有时会加上索引,但索引为什么能提高检索速率呢?是不是用了索引就一定可以提高效率呢?不同索引之间有什么区别呢?搞懂这些问题是灵活运用索引的必 ...
- githup上传文件
GitHub是基于git实现的代码托管.git是目前最好用的版本控制系统了,非常受欢迎,比之svn更好. GitHub可以免费使用,并且快速稳定.即使是付费帐户,每个月不超过10美刀的费用也非常便宜. ...
- Topshelf + Quartz2.5 创建基于windows服务
1.创建一个定时调度Quartz类 using Quartz; using Quartz.Impl; using System; using System.Collections.Generic; u ...
- Vue vue-resource发送Http请求
vue-resource 1.cnpm install vue-resource --save 2.在main.js中import VueResource from 'vue-resource' 3. ...
- 华硕X550VC安装ubuntu后wifi无法连接问题
在网上找了很多资料比如重新编译内核,想办法连上有线网络然后更新驱动,下载离线驱动安装包…… 等等方法 其中有些方法实际测试的时候失败了,文章是几年前的,可能缺少某些依赖.上个网都这么麻烦实在让人疲惫. ...
- 结对作业-WordCount进阶版
1.在文章开头给出博客作业要求地址. 博客园地址:https://www.cnblogs.com/happyzm/p/9559372.html 2.给出结对小伙伴的学号.博客地址,结对项目的码云地址. ...
- Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'blog.t_blog.addTime' which is not functi
sql报错: Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Expression #1 of SELECT ...