针对单一key加读写锁
一、什么是读写锁
读写锁是JDK1.5提供的一个工具锁,适用于读多写少的场景,将读写分离,从而提高并发性。
二、读写锁的特点
读锁是共享锁,写锁是排他锁,读锁和写锁不能同时存在;
读锁不能升级为写锁;
写锁可以降级为读锁;
三、锁的本质
锁的本质就是锁住一块资源而不是一块代码. 在常见的一些代码实现都是加一把大锁,将这一块代码资源统一加锁,无法针对资源进行精确进行锁控制.
四、代码实现
`
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
@Slf4j
public class UserDefinedLock {
final ConcurrentHashMap<String, ReadWriteLock> map = new ConcurrentHashMap<>();
public UserDefinedLock() {
}
/**
* 从map里获取锁 如果存在则返回 不存在则创建
*
* @param key key
* @return lock
*/
public void createOrGetLock(String key) {
synchronized (key.intern()) {
map.compute(key, (k, lock) -> {
if (lock == null) {
lock = new ReentrantReadWriteLock();
}
return lock;
});
}
}
/**
* 获取锁 会阻塞
*
* @param key key
*/
public void writeLock(String key) {
map.get(key).writeLock().lock();
}
public void readLock(String key) {
map.get(key).readLock().lock();
}
/**
* 释放锁 必须由申请锁的线程进行调用
*
* @param key key
*/
public void unWriteLock(String key) {
ReadWriteLock lock = map.get(key);
if (null != lock) {
try {
lock.writeLock().unlock();
} catch (Exception e) {
log.error("释放写锁失败,key:{}, msg:{}", key, e.getMessage());
}
}
}
public void unReadLock(String key) {
ReadWriteLock lock = map.get(key);
if (null != lock) {
try {
lock.readLock().unlock();
} catch (Exception e) {
log.error("释放读锁失败,key:{}, msg:{}", key, e.getMessage());
}
}
}
public static void main(String[] args) {
UserDefinedLock userDefinedLock = new UserDefinedLock();
ArrayList list = new ArrayList<String>();
for (int i = 0; i < 5; i++) {
String key = String.valueOf("测试" + i);
new Thread(() -> {
try {
userDefinedLock.createOrGetLock(key);
userDefinedLock.readLock(key);
System.out.println("-----" + key + "----");
list.add(key);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
userDefinedLock.unReadLock(key);
}
}, "read-" + key).start();
}
}
}
`
针对单一key加读写锁的更多相关文章
- Java并发编程原理与实战十八:读写锁
ReadWriteLock也是一个接口,提供了readLock和writeLock两种锁的操作机制,一个资源可以被多个线程同时读,或者被一个线程写,但是不能同时存在读和写线程. 基本规则: 读读不互斥 ...
- JAVA 并发编程-读写锁之模拟缓存系统(十一)
在多线程中,为了提高效率有些共享资源同意同一时候进行多个读的操作,但仅仅同意一个写的操作,比方一个文件,仅仅要其内容不变能够让多个线程同一时候读,不必做排他的锁定,排他的锁定仅仅有在写的时候须要,以保 ...
- Eureka中读写锁的奇思妙想,学废了吗?
前言 很抱歉 好久没有更新文章了,最近的一篇原创还是在去年十月份,这个号确实荒废了好久,感激那些没有把我取消关注的小伙伴. 有读者朋友经常私信问我: "你号卖了?" "文 ...
- linux使用读写锁pthread_rwlock_t
转自:http://blog.csdn.net/onlyou930/article/details/6755593 使用读写锁 配置读写锁的属性之后,即可初始化读写锁.以下函数用于初始化或销毁读写锁. ...
- UNIX环境高级编程——线程同步之读写锁以及属性
读写锁和互斥量(互斥锁)很类似,是另一种线程同步机制,但不属于POSIX标准,可以用来同步同一进程中的各个线程.当然如果一个读写锁存放在多个进程共享的某个内存区中,那么还可以用来进行进程间的同步, 互 ...
- golang map 读写锁与深度拷贝的坑
0X01 golang中,map(字典)无法并发读写 简单来说,新建万条线程对同一个map又读又写,会报错. 为此,最好加锁,其实性能影响并不明显. type taskCache struct{ sy ...
- linux c编程:读写锁
什么是读写锁读写锁其实还是一种锁,是给一段临界区代码加锁,但是此加锁是在进行写操作的时候才会互斥,而在进行读的时候是可以共享的进行访问临界区的 为什么需要读写锁有时候,在多线程中,有一些公共数据修改的 ...
- ReentrantReadWriteLock读写锁详解
一.读写锁简介 现实中有这样一种场景:对共享资源有读和写的操作,且写操作没有读操作那么频繁.在没有写操作的时候,多个线程同时读一个资源没有任何问题,所以应该允许多个线程同时读取共享资源:但是如果一个线 ...
- 一道面试题比较synchronized和读写锁
一.科普定义 这篇博文的两个主角“synchronized”和“读写锁” 1)synchronized 这个同步关键字相信大家都用得比较多,在上一篇“多个线程之间共享数据的方式”中也详细列举他的应用, ...
- [自制操作系统] 原子操作&核间中断&读写锁&PRWLock
本文主要为读论文Scalable Read-mostly Synchronization Using Passive Reader-Writer Locks的记录. 并将其在JOS上实现.其中包括la ...
随机推荐
- file类创建删除功能的方法-file类遍历(文件夹)目录功能
file类创建删除功能的方法 public boolean createNewFile():当且仅当具有该名称的文件尚不存在时,创建一个新的空文件.public boolean delete(︰删除由 ...
- 【Rust学习】内存安全探秘:变量的所有权、引用与借用
作者:京东零售 周凯 一.前言 Rust 语言由 Mozilla 开发,最早发布于 2014 年 9 月,是一种高效.可靠的通用高级语言.其高效不仅限于开发效率,它的执行效率也是令人称赞的,是一种少有 ...
- JAVA虚拟机05-内存溢出示例(jdk1.8)
1.JAVA虚拟机堆内存溢出OutOfMemoryError 1.1设置参数 -Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError 最小堆的大小20m 最大堆 ...
- Windows IIS下运行.NET Core程序
IIS下运行.NET Core程序 1.服务器上必须要安装 WindowsHosting WindowsHosting 下载地址:https://dotnet.microsoft.com/downlo ...
- 视觉SLAM:滑动窗口
1.SLAM问题 1.1建模 考虑某个状态 \(\xi\),以及一次与该变量相关的观测 \(r_{i}\).由于噪声存在,观测服从概率分布 \(p(r_{i}|\xi)\).多个观测时,各个测量值相互 ...
- j-link "the connected j-link is defective"问题的解决
出现这个原因是 J-link和J-link的驱动不匹配,比如J-link的固件太老,J-link驱动太新.因此要解决的话,要不就是换不同版本的J-link驱动,要不就是换J-Link或升级J-link ...
- ES6的Promise用法
一.是什么: promise是异步编程的一种解决方案,它是一个对象,可以获取异步操作的信息,它的出现改善了异步编程,避免了地狱回调,它比传统的解决方案回调函数和事件更合理和更强大 二.promise的 ...
- linux系统下,添加硬盘并挂载到操作系统的shell 脚本范例
#!/bin/sh #新添加硬盘挂载到操作系统 pvcreate /dev/sdb / / 一般新添加硬盘都是识别为sdb,当然,也不一定,要具体情况具体分析. vgcreate datavg / ...
- Xilinx URAM使用说明 UG573
UltraRAM Resources UltraRAM Summary UltraRAM 是单时钟.双端口.同步存储器,可用于 UltraScale+ 器件.由于 UltraRAM 与柱状(colum ...
- Vue 非单文件组件(不常用)3步骤(创建、注册、使用)和几个注意点、组件的本质(VueComponent)
Vue中使用组件的三大步骤: 1.定义组件(创建) 2.注册组件 3.使用组件(写组件标签) 一.如何定义一个组件? 使用Vue.extend(options)创建,其中options 和 new V ...