完全 模仿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. Centos7配置TiDB监控

    一: 1.1:http://192.168.1.12:3000/ 1.2:点击install Grafana wget https://dl.grafana.com/oss/release/grafa ...

  2. jsonp 实现原理

      Jsonp原理: 首先在客户端注册一个callback, 然后把callback的名字传给服务器. 此时,服务器先生成 json 数据.然后以 javascript 语法的方式,生成一个funct ...

  3. FCC JS基础算法题(9):Mutations(比较字符串)

    题目描述: 如果数组第一个字符串元素包含了第二个字符串元素的所有字符,函数返回true.举例,["hello", "Hello"]应该返回true,因为在忽略大 ...

  4. 关于CMD的一些小技巧

    1.cd命令无法切换路径怎么办? a)切换盘符不好使

  5. HTML知识点梳理1

    1,HTML基本结构 <!DOCTYPE html> <html> <head></head> <body> </body> & ...

  6. hdu 1874 畅通工程续 floyed

    裸题 题意:求任意两点之间的最短路径 坑点:测试数据同一条路径有可能出现多次,然后值不一样,注意筛选最小边 #include <iostream> #include <cstdio& ...

  7. java.io.EOFException ValueOperations.increment()操作后,获取值时有的bug

    ---恢复内容开始--- 今天使用spring-data-redis包操作redis,就是简单的使用redis的计数功能,在redis中的操作命令如:incr key;get key; 这两步操作使用 ...

  8. iso系统镜像刻录到光盘和U盘

    使用UltraISO刻录 刻录U盘,点击文件,打开,选择镜像 启动,写入硬盘镜像选择U盘即可 刻录光盘 工具,刻录光盘映像,选择镜像,需要先插入光盘刻录机(有些电脑可能自带光驱盘,且有刻录功能,那么我 ...

  9. zabbix与tomcat(六)

    一.zabbix监控远程tomcat的流程   Zabbix-server 找 zabbix Java Gateway获取Java数据 zabbix Java Gateway 找Java程序(zabb ...

  10. ubuntu18关闭系统自动更新

    ubuntu18.04关闭系统自动更新有两个方法:1.修改配置文件 修改配置文件/etc/apt/apt.conf.d/10periodic#0是关闭,1是开启,将所有值改为0vi etc/apt/a ...