Java限制可以重入次数的锁
完全 模仿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限制可以重入次数的锁的更多相关文章
- Java并发包源码学习系列:ReentrantLock可重入独占锁详解
目录 基本用法介绍 继承体系 构造方法 state状态表示 获取锁 void lock()方法 NonfairSync FairSync 公平与非公平策略的差异 void lockInterrupti ...
- java多线程系类:JUC锁:01之框架
本章,我们介绍锁的架构:后面的章节将会对它们逐个进行分析介绍.目录如下:01. Java多线程系列--"JUC锁"01之 框架02. Java多线程系列--"JUC锁&q ...
- Java多线程总结(二)锁、线程池
掌握Java中的多线程,必须掌握Java中的各种锁,以及了解Java中线程池的运用.关于Java多线程基础总结可以参考我的这篇博文Java多线程总结(一)多线程基础 转载请注明出处——http://w ...
- Java 线程 — synchronized、volatile、锁
线程同步基础 synchronized 和volatile是Java线程同步的基础. synchronized 将临界区的内容上锁,同一时刻只有一个进程能访问该临界区代码 使用的是内置锁,锁一个时刻只 ...
- Java并发编程之显式锁机制
我们之前介绍过synchronized关键字实现程序的原子性操作,它的内部也是一种加锁和解锁机制,是一种声明式的编程方式,我们只需要对方法或者代码块进行声明,Java内部帮我们在调用方法之前和结束时加 ...
- Java多线程与并发模型之锁
这是一篇总结Java多线程开发的长文.文章是从Java创建之初就存在的synchronized关键字引入,对Java多线程和并发模型进行了探讨.希望通过此篇内容的解读能帮助Java开发者更好的理清Ja ...
- Java并发包——线程同步和锁
Java并发包——线程同步和锁 摘要:本文主要学习了Java并发包里有关线程同步的类和锁的一些相关概念. 部分内容来自以下博客: https://www.cnblogs.com/dolphin0520 ...
- 死磕 java同步系列之zookeeper分布式锁
问题 (1)zookeeper如何实现分布式锁? (2)zookeeper分布式锁有哪些优点? (3)zookeeper分布式锁有哪些缺点? 简介 zooKeeper是一个分布式的,开放源码的分布式应 ...
- 死磕 java同步系列之redis分布式锁进化史
问题 (1)redis如何实现分布式锁? (2)redis分布式锁有哪些优点? (3)redis分布式锁有哪些缺点? (4)redis实现分布式锁有没有现成的轮子可以使用? 简介 Redis(全称:R ...
随机推荐
- CSS图形——实现圆角
css实现圆角 css2.1给元素添加圆角是一件很麻烦的事,老办法是用背景图片实现,制作比较麻烦.css3,border-radius的属性,使圆角属性得到完美的解决. 语法 border-radiu ...
- ipa 注入 dylib
前些日子再github找到了一个内存修改器 DLGMemor 免越狱在app内植入修改器,感觉很不错,就尝试去看看是否可行. 用到的工具: Xcode 10. optool 首先要做的,安装 opt ...
- Tex_安装_在Ubuntu系统下
$\LaTeX$是一个强大的排版软件,在数学公式.表格.甚至是科学绘图方面有着独特优势.本文在Ubuntu系统下,整理Tex安装相关的操作,以为备忘.所引链接都未同作者商量,如有不妥望及时告知. 命令 ...
- yarn不是内部指令 react-native不是内部指令
1.先查看是否全局安装 2.我遇到的是,全局安装了,依然有问题. 昨天装了一个高版本的node,成功后有个黑窗口我点了几个回车,在我的环境变量里加了一大推重复的变量,删除就正常了,如下图是我删完之后的
- Idea基于maven搭建多模块单体结构项目
菜鸟教程 一.创建一个公共的父工程: 1.1 创建一个新的maven项目: 1.2 先创建公共的父工程,选择maven骨架: 1.3 配置maven: 1.4 填写groupId.artifactId ...
- LeetCode - Unique Email Addresses
Every email consists of a local name and a domain name, separated by the @ sign. For example, in ali ...
- python, ImageFont
ImageFont模块定义了相同名称的类,即ImageFont类.这个类的实例存储bitmap字体,用于ImageDraw类的text()方法. PIL可以配置是否支持TrueType和OpenTyp ...
- Mysql组复制之单主模式(一)
环境 系统:CentOS release 6.9 (Final) Mysql:5.7 机器: S1 10.0.0.7 lemon S2 10.0.0.8 lemon2 S3 10.0.0.9 lemo ...
- java:try...catch...finally
try...catch...finally 规则: 可以没有 finally 块 如果没有 catch 块,则必须跟一个 finally 块 当在 try 块或 catch 块中遇到 return 语 ...
- golang 写日志到syslog
应用程序可以通过 UNIX domain sockets, UDP or TCP,向syslog守护进程发送日志.syslog守护进程可以在远端. 这样,就可以不用单独收集应用程序的日志了. gola ...