重入锁--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()方法起到了线程等待和通知 ...
随机推荐
- .netcore部署到IIS上出现HTTP Error 502.5 - Process Failure问题解决
首先网上是有很多解决方案,但是对我这个错误完全没用 如果你们没有环境首先得预装环境如下 1.首先在bing.com下搜索asp.net core download, 然后打开搜索到的信息.NET Do ...
- Sqlserver风格规范
常见的字段类型选择 1.字符类型建议采用varchar/nvarchar数据类型 2.金额货币建议采用money数据类型 3.科学计数建议采用numeric数据类型 4.自增长标识建议采用bigint ...
- MySql8.0后密码认证方式问题[caching-sha2-password]
这个问题通常在laravel中表现为类似下边的异常: local.ERROR: SQLSTATE[HY000] [2006] MySQL server has gone away {"exc ...
- javascript 视频播放指定的时间段
javascript 视频播放指定的时间段 一.html5 vedio: //指定开始时间 player.currentTime=startPoint; player.play(); //使用事件来控 ...
- ubuntu没有权限(不能)创建文件夹(目录)
可以在终端直接运行 sudo nautilus,弹出来的nautilus可以直接GUI操作,中途别关终端.如果遇到需要输入root密码,则输入root密码就可以启动这个图形界面了.
- bzoj2440完全平方数
题目链接 上来先吐槽题面!!!!!! 你跟我说$1$不是完全平方数昂? 看了半天样例啊. 活生生的半天$……$ 莫比乌斯 反演 函数容斥一下,每次二分就好 反正本宝宝不知道反演是啥. 每次判断应 ...
- redis原理及实现
1 什么是redis redis是nosql(也是个巨大的map) 单线程,但是可处理1秒10w的并发(数据都在内存中) 使用java对redis进行操作类似jdbc接口标准对mysql,有各类实现他 ...
- python之freshman00
编译型vs解释型 编译型优点:编译器一般会有预编译的过程对代码进行优化.因为编译只做一次,运行时不需要编译,所以编译型语言的程序执行效率高.可以脱离语言环境独立运行.缺点:编译之后如果需要修改就需要整 ...
- pip 使用代理
pip install -i https://mirrors.aliyun.com/pypi/simple/ opencv-python 红色部分 代表使用 阿里云 代理 安装 pip
- JDBC 连接 postgresql 时区变 UTC
加上 时区 语句 ..-Duser.timezone=PRC