使用AQS自定义重入锁
一、创建MyLock
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock; public class MyLock implements Lock { private Helper helper = new Helper(); @Override
public void lock() {
helper.acquire(1);
} @Override
public void lockInterruptibly() throws InterruptedException {
helper.acquireInterruptibly(1);
} @Override
public boolean tryLock() {
return helper.tryAcquire(1);
} @Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
return helper.tryAcquireNanos(1, unit.toNanos(time));
} @Override
public void unlock() {
helper.release(1);
} @Override
public Condition newCondition() {
return helper.newCondition();
} private class Helper extends AbstractQueuedSynchronizer {
@Override
protected boolean tryAcquire(int arg) {
//如果第一个线程进来,可以拿到锁,返回true //如果第二个线程进来,拿不到锁,返回false,有种特例,如果当前进来的线程和当前保存的线程是同一个线程,则可以拿到锁,但是要更新状态值 //如何判断是第一个线程进来还是其他线程进来 int state = getState();
Thread t = Thread.currentThread(); if (state == 0) {//判断是否是第一个线程
if (compareAndSetState(0, arg)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
} else if(getExclusiveOwnerThread() == t) {//判断当前进来的线程和当前保存的线程是否是同一个线程,实现重入锁,因为锁的是对象,所以只要是同一个Helper对象线程就是同一个线程
setState(state + 1);
return true;
}
return false;
} @Override
protected boolean tryRelease(int arg) {
//锁的获取和释放肯是一一对应的,那么调用此方法的线程一定是当前线程
if (Thread.currentThread() != getExclusiveOwnerThread()) {
throw new RuntimeException();
} int state = getState() - arg;
setState(state); if (state == 0) {
setExclusiveOwnerThread(null);
return true;
}
return false;
} protected ConditionObject newCondition() {
return new ConditionObject();
} }
}
二、编写测试代码
public class TestMyLock {
private int value;
private MyLock myLock = new MyLock();
public int getValue() {
myLock.lock();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
value ++;
myLock.unlock();
return value;
}
public void a() {
myLock.lock();
System.out.println("a");
b();
myLock.unlock();
}
public void b() {
myLock.lock();
System.out.println("b");
myLock.unlock();
}
public static void main(String[] args) {
TestMyLock testMyLock = new TestMyLock();
//检测是否会并发
Runnable runnable = () -> {
for (int i = 0; i<100; i++) {
System.out.println(Thread.currentThread().getId()+",值:" + testMyLock.getValue());
}
};
new Thread(runnable).start();
new Thread(runnable).start();
new Thread(runnable).start();
//检测重入锁
Runnable runnable1 = () -> testMyLock.a();
new Thread(runnable1).start();
}
}
使用AQS自定义重入锁的更多相关文章
- AQS与重入锁ReetrantLock原理
一.AQS原理 AQS(AbstractQueuedSynchronizer)队列同步器是用来构建锁.同步组件的基础框架. AQS内部通过一个volatile int类型的成员变量state控制同步状 ...
- Java并发编程原理与实战十七:AQS实现重入锁
一.什么是重入锁 可重入锁就是当前持有锁的线程能够多次获取该锁,无需等待 二.什么是AQS AQS是JDK1.5提供的一个基于FIFO等待队列实现的一个用于实现同步器的基础框架,这个基础框架的重要性可 ...
- Java并发编程:用AQS写一把可重入锁
Java并发编程:自己动手写一把可重入锁详述了如何用synchronized同步的方式来实现一把可重入锁,今天我们来效仿ReentrantLock类用AQS来改写一下这把锁.要想使用AQS为我们服务, ...
- AQS学习(二) AQS互斥模式与ReenterLock可重入锁原理解析
1. MyAQS介绍 在这个系列博客中,我们会参考着jdk的AbstractQueuedLongSynchronizer,从零开始自己动手实现一个AQS(MyAQS).通过模仿,自己造轮子来学习 ...
- Java多线程——深入重入锁ReentrantLock
简述 ReentrantLock 是一个可重入的互斥(/独占)锁,又称为“独占锁”. ReentrantLock通过自定义队列同步器(AQS-AbstractQueuedSychronized,是实现 ...
- j.u.c系列(05)---之重入锁:ReentrantLock
写在前面 ReentrantLock,可重入锁,是一种递归无阻塞的同步机制.它可以等同于synchronized的使用,但是ReentrantLock提供了比synchronized更强大.灵活的锁机 ...
- Java多线程系列——深入重入锁ReentrantLock
简述 ReentrantLock 是一个可重入的互斥(/独占)锁,又称为“独占锁”. ReentrantLock通过自定义队列同步器(AQS-AbstractQueuedSychronized,是实现 ...
- J.U.C之重入锁:ReentrantLock
此篇博客所有源码均来自JDK 1.8 ReentrantLock,可重入锁,是一种递归无阻塞的同步机制.它可以等同于synchronized的使用,但是ReentrantLock提供了比synchro ...
- Java 可重入锁的那些事(一)
本文主要包含的内容:可重入锁(ReedtrantLock).公平锁.非公平锁.可重入性.同步队列.CAS等概念的理解 显式锁 上一篇文章提到的synchronized关键字为隐式锁,会自动获取和自动释 ...
随机推荐
- mysql数据库-索引-长期维护
############### 索引介绍 ############## """ 1. 索引介绍 需求: 一般的应用系统,读写比例在10:1左右,而且插入操作和 ...
- [LC] 243. Shortest Word Distance
Given a list of words and two words word1 and word2, return the shortest distance between these two ...
- string删除与查找erase,find
s.erase( 指针位置 , 删除长度 ) 返回值修改后的string对象引用 find(string, int):第一个参数用来指示要查找的字符,第二个参数用来表示从字符串的何处开始查找子串(默认 ...
- input系统——android input系统
AndroidInput系统--JNI NativeInputManager InputManger InputReader AndroidInput系统--InputReader AndroidIn ...
- 是谁收购了被谷歌私藏7年之久的Zagat?
国内餐饮行业的风口似乎总是执着于"价格"上,无论是天天搞特价的外卖,还是优惠不停歇的团购网站,都将"价格"当做了竞争的杀手锏.即使是网红奶茶.甜品之类的,也是将 ...
- ranche2.0-CN
遵循以下两步,快速运行rancher2.0 Step1:准备一台linux主机 准备一台64位Linux主机(推荐centos7.5+),至少4GB内存.安装Kubernetes支持的Docker-c ...
- 吴裕雄--天生自然 PYTHON数据分析:钦奈水资源管理分析
df = pd.read_csv("F:\\kaggleDataSet\\chennai-water\\chennai_reservoir_levels.csv") df[&quo ...
- 数位dp对于状态描述与发现的一些感悟
今天刷的数位dp 第一题看了题解以后知道了数位dp的基本板子,写数位dp的方式(运用记忆化递归的方法)已经基本固定. 那么接下来的难点主要还是对于题目描述的问题,如何抽象成dp中的状态.就今天刷的题来 ...
- WWW 2015:一个神奇的会议
2015:一个神奇的会议" title="WWW 2015:一个神奇的会议"> 作者:微软亚洲研究院研究员 袁进辉 WWW 2015(24th Internatio ...
- 查漏补缺:Vector中去重
对于STL去重,可以使用<algorithm>中提供的unique()函数. unique()函数用于去除相邻元素中的重复元素(所以去重前需要对vector进行排序),只留下一个.返回去重 ...