一、创建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自定义重入锁的更多相关文章

  1. AQS与重入锁ReetrantLock原理

    一.AQS原理 AQS(AbstractQueuedSynchronizer)队列同步器是用来构建锁.同步组件的基础框架. AQS内部通过一个volatile int类型的成员变量state控制同步状 ...

  2. Java并发编程原理与实战十七:AQS实现重入锁

    一.什么是重入锁 可重入锁就是当前持有锁的线程能够多次获取该锁,无需等待 二.什么是AQS AQS是JDK1.5提供的一个基于FIFO等待队列实现的一个用于实现同步器的基础框架,这个基础框架的重要性可 ...

  3. Java并发编程:用AQS写一把可重入锁

    Java并发编程:自己动手写一把可重入锁详述了如何用synchronized同步的方式来实现一把可重入锁,今天我们来效仿ReentrantLock类用AQS来改写一下这把锁.要想使用AQS为我们服务, ...

  4. AQS学习(二) AQS互斥模式与ReenterLock可重入锁原理解析

    1. MyAQS介绍    在这个系列博客中,我们会参考着jdk的AbstractQueuedLongSynchronizer,从零开始自己动手实现一个AQS(MyAQS).通过模仿,自己造轮子来学习 ...

  5. Java多线程——深入重入锁ReentrantLock

    简述 ReentrantLock 是一个可重入的互斥(/独占)锁,又称为“独占锁”. ReentrantLock通过自定义队列同步器(AQS-AbstractQueuedSychronized,是实现 ...

  6. j.u.c系列(05)---之重入锁:ReentrantLock

    写在前面 ReentrantLock,可重入锁,是一种递归无阻塞的同步机制.它可以等同于synchronized的使用,但是ReentrantLock提供了比synchronized更强大.灵活的锁机 ...

  7. Java多线程系列——深入重入锁ReentrantLock

    简述 ReentrantLock 是一个可重入的互斥(/独占)锁,又称为“独占锁”. ReentrantLock通过自定义队列同步器(AQS-AbstractQueuedSychronized,是实现 ...

  8. J.U.C之重入锁:ReentrantLock

    此篇博客所有源码均来自JDK 1.8 ReentrantLock,可重入锁,是一种递归无阻塞的同步机制.它可以等同于synchronized的使用,但是ReentrantLock提供了比synchro ...

  9. Java 可重入锁的那些事(一)

    本文主要包含的内容:可重入锁(ReedtrantLock).公平锁.非公平锁.可重入性.同步队列.CAS等概念的理解 显式锁 上一篇文章提到的synchronized关键字为隐式锁,会自动获取和自动释 ...

随机推荐

  1. Linux 设置开机启动项的几种方法

    方法一:编辑rc.loacl脚本 Ubuntu开机之后会执行/etc/rc.local文件中的脚本. 所以我们可以直接在/etc/rc.local中添加启动脚本. $ vim /etc/rc.loca ...

  2. 【mysql学习】InnoDB数据结构

    原来知道有一些索引失效的条件,最近看了看mysql底层数据结构,明白了为什么会失效 ,记录之.众所周知,常用的mysql数据引擎有两种,今天全是以InnoDB为基础开启探索之旅的,另一种有时间再说吧. ...

  3. socket握手SYN和ACK理解

    ACK 英文缩写: ACK (ACKnowledge Character) 中文译名: 确认字符 分类: 传输与接入 解释: 在数据通信传输中,接收站发给发送站的一种传输控制字符.它表示确认发来的数据 ...

  4. 61)PHP,立即跳转

    一般使用   header(‘Location:’)来进行跳转. ******************************************************************* ...

  5. Fire-Fighting Hero(多源最短路和单源最短路)

    题:https://nanti.jisuanke.com/t/41349 分析:对于hero来说,走单源最短路,然后遍历dis数组中的最大值即可找到,对于消防员来说,走多源最短路,只需要建个超级起点连 ...

  6. python学习笔记(1)python数据类型

    一.数据类型计算机顾名思义就是可以做数学计算的机器,因此,计算机程序理所当然地可以处理各种数值.但是,计算机能处理的远不止数值,还可以处理文本.图形.音频.视频.网页等各种各样的数据,不同的数据,需要 ...

  7. HDU-6672-Seq

    题目传送门 ps:一般这种给一个数列求第n项,n还特别大的.要么矩阵快速幂,要么转化递推式.不过这题数据也特别多有100000组,所以就算矩阵快速幂可能也要超时,而且我还没推出来.转化递推式需要比较强 ...

  8. Xpath 入门教程

    准备xml 文档 <?xml version="1.0" encoding="UTF-8"?> <bookstore> <book ...

  9. java实现银行管理系统

    Bank类 package First; import java.util.TreeSet; //银行类public class Bank {        private String Bankna ...

  10. wios设置证书登陆

    设置wios为密钥登陆set service ssh 'allow-root' set service ssh 'disable-password-authentication' //禁用密码登陆 s ...