完全 模仿ReentrantLock, 通过继承 java.util.concurrent.locks.Lock , 内置 AbstractQueuedSynchronizer 实现类,限制可以重入次数的锁。

这个其实不难, 只要稍微注意一点就好了

ReenterLimitedLock  关键实现:

/**
* l.k
*
* 限制可以重入次数的锁,默认是2次
*
*/
public class ReenterLimitedLock implements Lock, java.io.Serializable {
private static final long serialVersionUID = 7373984872572414699L;
private final Sync sync; /**
* Creates an instance of {@code ReenterLimitedLock}.
* This is equivalent to using {@code ReenterLimitedLock(false)}.
*/
public ReenterLimitedLock() {
sync = new NonfairSync(2);
} public ReenterLimitedLock(int reenterLimit) {
sync = new NonfairSync(reenterLimit);
} public ReenterLimitedLock(boolean fair, int reenterLimit) {
sync = fair ? new FairSync(reenterLimit) : new NonfairSync(reenterLimit);
} public ReenterLimitedLock(boolean fair) {
sync = fair ? new FairSync(2) : new NonfairSync(2);
} abstract static class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = -5179523762034025860L;
private boolean exceeded;
private int reenterLimit; public Sync(int reenterLimit) {
this.reenterLimit = reenterLimit;
} abstract void lock(); final boolean nonfairTryAcquire(int acquires) throws MaximumLockCountExceededException {
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
if (nextc > reenterLimit) { // 关键
exceeded = true;
// return false;
// throw new IllegalStateException("Maximum lock count exceeded" + 2);
throw new MaximumLockCountExceededException(reenterLimit);
}
setState(nextc);
return true;
}
return false;
} protected final boolean tryRelease(int releases) {
if (isExceeded()) {
return false;
}
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
} protected final boolean isHeldExclusively() {
// While we must in general read state before owner,
// we don't need to do so to check if current thread is owner
return getExclusiveOwnerThread() == Thread.currentThread();
} final ConditionObject newCondition() {
return new ConditionObject();
} // Methods relayed from outer class final Thread getOwner() {
return getState() == 0 ? null : getExclusiveOwnerThread();
} final int getHoldCount() {
return isHeldExclusively() ? getState() : 0;
} final boolean isLocked() {
return getState() != 0;
} /**
* Reconstitutes the instance from a stream (that is, deserializes it).
*/
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject();
setState(0); // reset to unlocked state
} public boolean isExceeded() {
return exceeded;
} public void setExceeded(boolean exceeded) {
this.exceeded = exceeded;
} public int getReenterLimit() {
return reenterLimit;
} public void setReenterLimit(int reenterLimit) {
this.reenterLimit = reenterLimit;
} } /**
* Sync object for non-fair locks
*/
static final class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L; public NonfairSync(int reenterLimit) {
super(reenterLimit);
} /**
* Performs lock. Try immediate barge, backing up to normal
* acquire on failure.
*/
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
} protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
} /**
* Sync object for fair locks
*/
static final class FairSync extends Sync {
private static final long serialVersionUID = -3000897897090466540L; public FairSync(int reenterLimit) {
super(reenterLimit);
} final void lock() {
acquire(1);
} /**
* Fair version of tryAcquire. Don't grant access unless
* recursive call or no waiters or is first.
*/
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)
if (nextc > getReenterLimit()) // 这里是关键
throw new MaximumLockCountExceededException(getReenterLimit());
// throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
} public void lock() {
sync.lock();
} public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
} public boolean tryLock() {
return sync.nonfairTryAcquire(1);
} public boolean tryLock(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireNanos(1, unit.toNanos(timeout));
} public void unlock() {
sync.release(1);
} public Condition newCondition() {
return sync.newCondition();
} public int getHoldCount() {
return sync.getHoldCount();
} public boolean isHeldByCurrentThread() {
return sync.isHeldExclusively();
} public boolean isLocked() {
return sync.isLocked();
} public final boolean isFair() {
return sync instanceof FairSync;
} protected Thread getOwner() {
return sync.getOwner();
} public final boolean hasQueuedThreads() {
return sync.hasQueuedThreads();
} public final boolean hasQueuedThread(Thread thread) {
return sync.isQueued(thread);
} public final int getQueueLength() {
return sync.getQueueLength();
} protected Collection<Thread> getQueuedThreads() {
return sync.getQueuedThreads();
} public boolean hasWaiters(Condition condition) {
if (condition == null)
throw new NullPointerException();
if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
throw new IllegalArgumentException("not owner");
return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition);
} public int getWaitQueueLength(Condition condition) {
if (condition == null)
throw new NullPointerException();
if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
throw new IllegalArgumentException("not owner");
return sync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject)condition);
} protected Collection<Thread> getWaitingThreads(Condition condition) {
if (condition == null)
throw new NullPointerException();
if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
throw new IllegalArgumentException("not owner");
return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition);
} public String toString() {
Thread o = sync.getOwner();
return super.toString() + ((o == null) ?
"[Unlocked]" :
"[Locked by thread " + o.getName() + "]");
}
}

MaximumLockCountExceededException 异常:

public class MaximumLockCountExceededException extends IllegalStateException {
//public class MaximumLockCountExceededException extends Exception {
public MaximumLockCountExceededException(String s) {
super(s);
}
public MaximumLockCountExceededException(int n) {
super("Maximum lock count exceeded: " + n);
}
}

测试:

/**
* Created by L.k on 2018/11/29.
*/
public class Testaa { ReenterLimitedLock twiceLock = new ReenterLimitedLock(); public static void main(String[] args) {
ReenterLimitedLock twiceLock = new ReenterLimitedLock();
Testaa testaa = new Testaa(twiceLock);
testaa.aa("asf");
} public Testaa(ReenterLimitedLock twiceLock) {
this.twiceLock = twiceLock;
} public void aa(String aa) {
try {
twiceLock.lock();
Thread.sleep(1000);
System.out.println("aa = [" + aa + "]");
bb(aa);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
twiceLock.unlock();
}
} public void bb(String bb) {
try {
twiceLock.lock();
Thread.sleep(1000); System.out.println("bb = [" + bb + "]"); cc(bb); System.out.println("Testaa.bb"); } catch (InterruptedException e) {
e.printStackTrace();
} finally {
twiceLock.unlock();
}
} public void cc(String cc) {
try {
twiceLock.lock();
Thread.sleep(1000); System.out.println("cc = [" + cc + "]"); } catch (InterruptedException e) {
e.printStackTrace();
// } catch (InterruptedException | IllegalStateException e) {
} catch (MaximumLockCountExceededException e) { // 这里必须要 捕获 MaximumLockCountExceededException, 否则 bb 方法也会异常退出
// e.printStackTrace();
System.out.println("xxxx IllegalStateException = " + e);
} finally {
twiceLock.unlock();
}
}
}

Java限制可以重入次数的锁的更多相关文章

  1. Java并发包源码学习系列:ReentrantLock可重入独占锁详解

    目录 基本用法介绍 继承体系 构造方法 state状态表示 获取锁 void lock()方法 NonfairSync FairSync 公平与非公平策略的差异 void lockInterrupti ...

  2. java多线程系类:JUC锁:01之框架

    本章,我们介绍锁的架构:后面的章节将会对它们逐个进行分析介绍.目录如下:01. Java多线程系列--"JUC锁"01之 框架02. Java多线程系列--"JUC锁&q ...

  3. Java多线程总结(二)锁、线程池

    掌握Java中的多线程,必须掌握Java中的各种锁,以及了解Java中线程池的运用.关于Java多线程基础总结可以参考我的这篇博文Java多线程总结(一)多线程基础 转载请注明出处——http://w ...

  4. Java 线程 — synchronized、volatile、锁

    线程同步基础 synchronized 和volatile是Java线程同步的基础. synchronized 将临界区的内容上锁,同一时刻只有一个进程能访问该临界区代码 使用的是内置锁,锁一个时刻只 ...

  5. Java并发编程之显式锁机制

    我们之前介绍过synchronized关键字实现程序的原子性操作,它的内部也是一种加锁和解锁机制,是一种声明式的编程方式,我们只需要对方法或者代码块进行声明,Java内部帮我们在调用方法之前和结束时加 ...

  6. Java多线程与并发模型之锁

    这是一篇总结Java多线程开发的长文.文章是从Java创建之初就存在的synchronized关键字引入,对Java多线程和并发模型进行了探讨.希望通过此篇内容的解读能帮助Java开发者更好的理清Ja ...

  7. Java并发包——线程同步和锁

    Java并发包——线程同步和锁 摘要:本文主要学习了Java并发包里有关线程同步的类和锁的一些相关概念. 部分内容来自以下博客: https://www.cnblogs.com/dolphin0520 ...

  8. 死磕 java同步系列之zookeeper分布式锁

    问题 (1)zookeeper如何实现分布式锁? (2)zookeeper分布式锁有哪些优点? (3)zookeeper分布式锁有哪些缺点? 简介 zooKeeper是一个分布式的,开放源码的分布式应 ...

  9. 死磕 java同步系列之redis分布式锁进化史

    问题 (1)redis如何实现分布式锁? (2)redis分布式锁有哪些优点? (3)redis分布式锁有哪些缺点? (4)redis实现分布式锁有没有现成的轮子可以使用? 简介 Redis(全称:R ...

随机推荐

  1. mail语法

    在Linux系统下mail命令的用法 在Linux系统下mail命令的测试 1. 最简单的一个例子: mail -s test admin@aispider.com 这条命令的结果是发一封标题为tes ...

  2. Fescar Example-Spring Cloud

    项目说明 本项目演示如何使用 Fescar Starter 完成 Spring Cloud 应用的分布式事务接入. 准备工作 在运行此示例之前,你需要先完成如下几步准备工作: 配置数据库 创建 UND ...

  3. 由一次报错引发的对于Spring创建对象的理解

    org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'ent ...

  4. Sublime Keymap 设置

    深深受 Emacs 组合键的影响,在编辑的时候使用组合键快速移动,而不比像 VIM 需要切换模式,但不得不吐槽 Emacs 的插件安装那个叫恶心,所以尝试了新生代产品 Sublime,但是还是离不开 ...

  5. springmvc简单集成shiro

    前言: 有天和同事聊天, 谈起权限管理, 他说他有个同事用shiro用的很溜. 正好现在有个管理平台项目, 有权限控制的需求, 因此想借此机会研究一番. 本文主要简单讲解一下对shiro的一些认识, ...

  6. latex之插入向量、图片、编号

    1.向量 $\vec a$\qquad $\overleftarrow{AB}$\qquad $\overleftrightarrow{AB}$\qquad $\overrightarrow{AB}$ ...

  7. 浅谈HTTP和HTTPS的区别

    这篇随笔我们从六个步骤来学习: 1.了解HTTP和HTTPS的基本概念 2.HTTPS诞生的目的 3.HTTP与HTTPS的区别 4.HTTP和HTTPS的工作原理 5.HTTPS的优缺点 6.如何将 ...

  8. 日常遇错之ModuleNotFoundError: No module named request

    用pycharm写python的时候,import request时,报错:ModuleNotFoundError: No module named request emmmm.解决方法:pip in ...

  9. JavaScript 堆排序详解

    堆通常实现为全完二叉树,二叉堆一般分为两种:最大堆和最小堆.堆排序就是通过将数组转换成最大堆结构再进行排序. // 原理:把数组转换成最大堆来排序.把堆顶的最大数取出,将剩余的堆继续调整为最大堆,再次 ...

  10. 在子页面操作父页面元素和iframe说明

    实现功能:在子页面操作父页面元素. 在实际编码的过程中,大家一定有这种需求:在父级页面有一个<iframe scrolling='auto'></iframe>内联框架,而我们 ...