一、创建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. set|lambda|reduce

    #!/usr/bin/python a=set([i for i in range(4,8)]) b=set([i for i in range(5,12)]) c= sorted(a & b ...

  2. Number of Digit One(Medium)

    1.算法说明: 如3141592,在m(digitDivide)=100时,即要求计算百位上"1"的个数 其中a为31415,b为92,31415中出现了3142次"1& ...

  3. QuickSort(快速排序)原理及C++代码实现

    快速排序可以说是最重要的排序,其中延伸的思想和技巧非常值得我们学习. 快速排序也使用了分治的思想,原理如下: 分解:数组A[p..r]被划分为两个(可能为空)子数组A[p..q-1]和A[q+1..r ...

  4. 58)PHP,后台登录步骤示意图

    注意上面的action提交位置: 并且注意下面的两个东西:

  5. CAS 5.3.x 相关信息

    CAS 5.3.x 相关信息 单点登录系统 学习网站: https://www.apereo.org/projects/cas 官方网站 https://github.com/apereo/cas-o ...

  6. deeplearning.ai 构建机器学习项目 Week 2 机器学习策略 II

    1. 误差分析(Error analysis) 误差分析的目的是找到不同误差源的比重,从而指引我们接下来往哪个方向努力改进.NG建议手工统计随机100个错误的误差源,比如对于猫分类器,错误的照片可能是 ...

  7. SHELL用法四(for语句)

    1.SHELL编程For语句案例实战 1)For语句固定的语法格式: For i in (表达式) do 动作1 done 2)For语句案例操作一: #!/bin/bash do echo “$NU ...

  8. css - 原生变量及使用函数 var()

    零.序言 前两天在逛 blog 的时候看见一些内联样式新奇的写法时很纳闷,虽然说不上多么熟练,但是从来没见过  --color: brown 这样的写法,百度一番之后仍然没啥头绪,今天偶然看到一篇文章 ...

  9. 2018湖南省赛B题“2018”

    题面懒得敲了,反正看这篇博客的肯定知道题面. 比赛时想按约数的一些性质分情况讨论出公式然后在合并,结果单考虑矩阵里出现2018和1009(与2互质,1009出现次数等于2)出现的情况就写了一长串公式, ...

  10. 使用JS-SDK自定义微信分享效果

    前言 刚进入一家新公司,接到的第一个任务就是需要需要自定义微信分享的效果(自定义缩略图,标题,摘要),一开始真是一脸懵逼,在网上搜索了半天之后大概有了方案.值得注意的是一开始搜索到的解决方案全是调用微 ...