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 ...
随机推荐
- neutron之neutron_openvswitch_agent占用100%CPU资源问题
基于kolla-ansible部署的queens版本,基于docker stats查看openstack的资源占用,发现neutron_openvswitch_agent一直占用100%CPU资源,这 ...
- Java语法基础学习DaySixteen(多线程)
一.多线程的创建 1.作用 程序需要同时执行两个或多个任务时需要多线程. 程序需要实现需要等待的任务时,如用户输入.文件读写操作.网络操作.搜索等,需要多线程. 需要一些后台运行的程序时,需要多线程. ...
- java学习笔记41(数据库连接池 C3p0连接池)
在之前的学习中,我们发现,我们需要频繁的创建连接对象,用完之后还需要在关闭资源,因为这些连接对象都是占资源的,但是又不得不创建,比较繁琐,为了解决这种情况,Java出现了数据库连接池: 数据库连接池的 ...
- 微信小程序用setData给数组对象赋值
假如现在要给数组marker中的对象属性赋值 data: { marker: [ { latitude: ' ' , longitude: ' ' } ] }, 在方法中的写法为 fetchJ ...
- Gym - 100783G:Playing With Geometry (几何 离散化 )
pro:给定规则的多边形,规则是指顶点都在整点上,而且是相互垂直的边的交点. 现在给定两个多边形A,B,问A,B缩小,旋转后是否可以变为同一个图形. sol:缩小的话,直接离散化即可,就可以去掉没用的 ...
- JavaScript常见的继承方式
原型链机制: 在ECMAscript中描述了原型链的概念,并将原型链作为实现继承的主要方法,其基本思想就是利用原型让一个引用类型继承另一个引用类型的属性和方法. 构造函数和原型还有实例之间的关系: 每 ...
- Codeforces1062D. Fun with Integers(埃氏筛)
题目链接:传送门 题目: D. Fun with Integers time limit per test seconds memory limit per test megabytes input ...
- 什么是web前端开发?
Web前端开发工程师,主要职责是利用(X)HTML/CSS/JavaScript/Flash等各种Web技术进行客户端产品的开发.完成客户端程序(也就是浏览器端)的开发,开发JavaScript以及F ...
- How to create an rpm package
转自:https://linuxconfig.org/how-to-create-an-rpm-package Rpm is both the package manager and the pack ...
- ARTIFICIAL INTELLIGENCE FOR GAMES (Ian Millington / John Funge 著)
相关网站:http://www.ai4g.com PART I AI AND GAMESCHAPTER1 INTRODUCTIONCHAPTER2 GAME AIPART II TECHNIQUESC ...