重入锁--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()方法起到了线程等待和通知 ...
随机推荐
- Javascript脚本 : eval()函数
Javascript 中 eval(X)函数 是将参数 当做语句来执行 var number1='1+2'; alert(number1); 输出为 '12': var number2=eval('1 ...
- MySQL联合索引运用-最左匹配原则
前言 之前看了很多关于MySQL索引的文章也看了<高性能MySQL>这本书,自以为熟悉了MySQL索引使用原理,入职面试时和面试官交流,发现对复合索引的使用有些理解偏颇,发现自己的不足整理 ...
- [转] SAAS, PAAS, IAAS
SaaS:软件即服务.如CRM.HRM.SCM等等,是可以直接使用的,所以是和多数用户接触最多的一个层面,典型的比如CRM类软件SalesForce. PaaS:平台即服务.如数据挖掘.系统管理.编程 ...
- js工具库简单介绍
javascript mvc的解决方案: angularjs, backbone,underscore, 有空的时候了解一下. 移动端的几个需要了解一下,jq mobile, zepto.knocko ...
- xp 专业版组策略只有系统组件
想要不显示任务栏的提示消息,需要在组策略里面设置,(在"开始→运行"中输入"GPEDIT.MSC"打开组策略,然后依次选择"用户配置→管理模板→任务栏 ...
- SQL SERVER2008 R2修改Server Collation--文檔沒細看先存下來.
HOW TO: RESTORE THE MASTER DATABASE IN SQL SERVER 2012 by Thomas LaRock | Jan 14, 2014 | MSSQL, SQL ...
- 一、认识Node.js
1.什么是Note.js? 简单的说 Node.js 就是运行在服务端的 JavaScript.Node.js 是一个 Javascript 运行环境(runtime).它让 JavaScript 可 ...
- 指针和动态分配内存 (不定长度数组)------新标准c++程序设计
背景: 数组的长度是定义好的,在整个程序中固定不变.c++不允许定义元素个数不确定的数组.例如: int n; int a[n]; //这种定义是不允许的 但是在实际编程中,往往会出现要处理的数据数量 ...
- 运维利器:钉钉机器人脚本告警(Linux Python 篇)
写在前面的话 在前面的博客中已经具体提到了如何获取对的机器人的 Token 等操作,不清楚的可以参考之前写的 [运维利器:钉钉机器人脚本告警(Linux Shell 篇)]这篇博客的前部分. 本文主要 ...
- 用C语言构建一个可执行程序的流程
1.流程图 从用C语言写源代码,然后经过编译器.连接器到最终可执行程序的流程图大致如下图所示. 2.编译流程 首先,我们先用C语言把源代码写好,然后交给C语言编译器.C语言编译器内部分为前端和后端. ...