重入锁--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()方法起到了线程等待和通知 ...
随机推荐
- 【C#】CLR内存那点事(string)
string是比特殊的类,说引用类型,但不存在堆里面,而且String str=new String("HelloWorld")这样的重装也说没有的. 我们先来看一个方法 clas ...
- [.net 多线程]Mutex
Mutex是可以进程间同步的同步基元. 名称 说明 Mutex() 使用默认属性初始化 Mutex 类的新实例. Mutex(Boolean) 使用 Boolean 值(指示调用线程是否应具有互斥 ...
- php 可变数量的参数列表
可变数量的参数列表 PHP 在用户自定义函数中支持可变数量的参数列表.在 PHP 5.6 及以上的版本中,由 ... 语法实现:在 PHP 5.5 及更早版本中,使用函数func_num_args() ...
- Android app如何加密?
欢迎访问网易云社区,了解更多网易技术产品运营经验. Android App包含的内容有dex文件,so文件,res,assets资源文件.对应的加密按此内容分为三大方面:dex保护.so加密.资源保护 ...
- L - Ch’s gift HDU - 6162
Ch’s gift Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total S ...
- 《C#多线程编程实战》2.5 AutoResetEvent
这个有点像是缩小版的mutex 还是很好理解的 相对mutex 使用的范围可能比较小一点. class Program { static AutoResetEvent work = new AutoR ...
- NSURLConnection 网络请求
前言 DEPRECATED: The NSURLConnection class should no longer be used. NSURLSession is the replacement f ...
- 20165219 预备作业3 Linux安装及学习
20165219 预备作业3 Linux安装及学习 安装虚拟机 在安装的过程中遇到了不少的问题,在同学的帮助下都得到了解决.比如在新建虚拟机的时候没有64位这个选项,后来知道需要开启虚拟化,然后是安装 ...
- 自定义内核启动后的Logo
1.使用图像GIMP工具 2.详细步骤如下: A.将800x480的图片导入到GIMP工具. B.选中GIMP菜单栏进行以下操作 图像 -->模式 ...
- Touchable类组件
Touchable /* * React Native中提供3个组件用于给其他没有触摸事件的组件,绑定触摸事件 * TouchableOpacity 透明触摸,点击时,组件会出现透明过渡的效果 * T ...