-
Java高并发26-释放锁以及ReentrantLock实例演示
一、释放锁
1.void unlock()方法
-
尝试释放锁,如果当前线程持有锁,则调用该方法会让该线程对该线程持有的AQS状态值减1,如果减去1后当前状态值为0,则当前线程会释放该锁,否则仅仅减去1而已,如果当前线程没有持有该锁而调用了该方法就会抛出IllegalMonitorStateException异常,代码如下
public void unlock() {
sync.release();
}
public final boolean tryRelease( int releases) {
// 如果不是锁持有者,则调用 unlock则抛出异常
int c = getState() - releases;
if(Thread.currentThread() != getExclusiveOwnerThread()) {
throw new IllegalMonitorStateException();
}
boolean free = false;
// 如果当前可重入的次数为0,则清空锁持有线程
if(c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
// 设置可重入次数为原始值-1
setState(c);
return free;
}
-
如上述代码,如果当前线程不是该锁的持有者则直接抛出异常,否则查看状态值是否为0,为0则说明当前线程要放弃对该锁的持有权,则执行代码把当前锁的持有者设置为null,如果状态值不为0,则仅仅让当前线程对该锁的可重入次数减1.
2.下面以一个案例作为讲解
package com.ruigege.LockSourceAnalysis6;
import java.util.ArrayList;
public static class ReentrantLockList {
//线程不安全的List
private ArrayList<String> array = new ArrayList<String>();
//独占锁
private volatile ReentrantLock lock = new ReentrantLock();
//添加元素
public void add(String e) {
lock.lock();
try {
array.add(e);
}finally {
lcok.unlock();
}
}
//删除元素
public void remove(String e) {
lock.lock();
try {
array.remove(e);
}finally {
lock.unlock();
}
}
//获取数据
public String get(int index) {
lock.lock();
try {
return array.get(index);
}finally {
lock.unlock();
}
}
}
-
上述代码实现了一个线程不安全的array,当一个线程获取到锁的时候,进行一系列的增删改查,如果有其他线程想要获取到该锁,那么就会被放到AQS的队列中,等待第一个线程释放锁,来供它们获取。
二、读写锁ReentrantReadWriteLock的原理
-
解决线程安全问题只需要ReentrantLock即可,但是大多数情况下,该锁是独占锁,某时只有一个线程可以获取到该锁,那么实际上大多情况是写少读多,显然这个场景是无法满足的。所以ReentrantReadWriteLock就应运而生了,ReentrantReadWriteLock采用的时读写分离的策略,可以允许多个线程同时获取锁。 -
我们下次再来解析这个类
三、源码:
-
所在包:com.ruigege.ConcurrentListSouceCodeAnalysis5 -
https://github.com/ruigege66/ConcurrentJava
-
CSDN:https://blog.csdn.net/weixin_44630050 -
博客园:https://www.cnblogs.com/ruigege0000/
出 处:https://www.cnblogs.com/ruigege0000/p/14665173.html
最新更新
带有参数的装饰器
类装饰器
django中的auth模块与admin后台管理
python的日期处理
字符串常用方法
基本数据类型概述
python-map()函数基本用法
python带你实现任意下载AcFun视频数据~
bbs项目之注册功能
变量的定义和使用
三大常用数据库事务详解之三:事务运行
三大常用关系型数据库事务详解之二:基
三大关系型数据库事务详解之一:基本概
MongoDB常用命令(2)
MongoDB基本介绍与安装(1)
SQLServer触发器调用JavaWeb接口
SQL Server索引的原理深入解析
SqlServer2016模糊匹配的三种方式及效率问题
SQL中Truncate的用法
sqlserver 多表关联时在where语句中慎用tri
VB.NET中如何快速访问注册表
ASP.NET中图象处理过程详解
Vue(1)Vue安装与使用
JavaScript 语言入门
js将一段字符串的首字母转成大写
纯原生html编写的h5视频播放器
H5仿原生app短信验证码vue2.0组件附源码地
TypeScript(4)接口
TypeScript(3)基础类型
TypeScript(2)WebStorm自动编译TypeScript配置