一、什么是读写锁

读写锁是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加读写锁的更多相关文章

  1. Java并发编程原理与实战十八:读写锁

    ReadWriteLock也是一个接口,提供了readLock和writeLock两种锁的操作机制,一个资源可以被多个线程同时读,或者被一个线程写,但是不能同时存在读和写线程. 基本规则: 读读不互斥 ...

  2. JAVA 并发编程-读写锁之模拟缓存系统(十一)

    在多线程中,为了提高效率有些共享资源同意同一时候进行多个读的操作,但仅仅同意一个写的操作,比方一个文件,仅仅要其内容不变能够让多个线程同一时候读,不必做排他的锁定,排他的锁定仅仅有在写的时候须要,以保 ...

  3. Eureka中读写锁的奇思妙想,学废了吗?

    前言 很抱歉 好久没有更新文章了,最近的一篇原创还是在去年十月份,这个号确实荒废了好久,感激那些没有把我取消关注的小伙伴. 有读者朋友经常私信问我: "你号卖了?" "文 ...

  4. linux使用读写锁pthread_rwlock_t

    转自:http://blog.csdn.net/onlyou930/article/details/6755593 使用读写锁 配置读写锁的属性之后,即可初始化读写锁.以下函数用于初始化或销毁读写锁. ...

  5. UNIX环境高级编程——线程同步之读写锁以及属性

    读写锁和互斥量(互斥锁)很类似,是另一种线程同步机制,但不属于POSIX标准,可以用来同步同一进程中的各个线程.当然如果一个读写锁存放在多个进程共享的某个内存区中,那么还可以用来进行进程间的同步, 互 ...

  6. golang map 读写锁与深度拷贝的坑

    0X01 golang中,map(字典)无法并发读写 简单来说,新建万条线程对同一个map又读又写,会报错. 为此,最好加锁,其实性能影响并不明显. type taskCache struct{ sy ...

  7. linux c编程:读写锁

    什么是读写锁读写锁其实还是一种锁,是给一段临界区代码加锁,但是此加锁是在进行写操作的时候才会互斥,而在进行读的时候是可以共享的进行访问临界区的 为什么需要读写锁有时候,在多线程中,有一些公共数据修改的 ...

  8. ReentrantReadWriteLock读写锁详解

    一.读写锁简介 现实中有这样一种场景:对共享资源有读和写的操作,且写操作没有读操作那么频繁.在没有写操作的时候,多个线程同时读一个资源没有任何问题,所以应该允许多个线程同时读取共享资源:但是如果一个线 ...

  9. 一道面试题比较synchronized和读写锁

    一.科普定义 这篇博文的两个主角“synchronized”和“读写锁” 1)synchronized 这个同步关键字相信大家都用得比较多,在上一篇“多个线程之间共享数据的方式”中也详细列举他的应用, ...

  10. [自制操作系统] 原子操作&核间中断&读写锁&PRWLock

    本文主要为读论文Scalable Read-mostly Synchronization Using Passive Reader-Writer Locks的记录. 并将其在JOS上实现.其中包括la ...

随机推荐

  1. GPIO-CH32x系列芯片GPIO使用注意事项

    一.特殊IO使用注意事项 芯片型号:CH32F203C8T6.CH32V203C8T6 特殊IO:PC13.PC14.PC15 注意事项说明: 1.PC13~PC15的IO功能受限,速度必须限制在2M ...

  2. Nacos注册中心 (介绍与配置)

    Nacos注册中心 和Euraka一样都是注册中心,但Nacos不需要注册Nacos,因为阿里巴巴已经注册在好了.只需要下载安装后打开即可 Windows安装 开发阶段采用单机安装即可 1.1.下载安 ...

  3. 2023牛客寒假算法基础集训营6 A-L

    比赛链接 A 题解 知识点:模拟. 如题. 代码 #include <bits/stdc++.h> using namespace std; using ll = long long; i ...

  4. 3分钟安装fcpx10.6.5最新 小白一看就会 简体中文版 (亲测有效)

    Final Cut Pro 简介 Final Cut Pro X for Mac是苹果推出的一款功能强大的视频编辑软件,具有先进的调色功能.HDR 视频支持,以及 ProRes RAW,让剪辑.音轨. ...

  5. 四数相加II & 赎金信 & 三数之和 & 四数之和

    一.四数相加Ⅱ 454. 四数相加 II 1.方法概述 首先定义一个map,key放a和b两数之和,value 放a和b两数之和出现的次数.遍历大A和大B数组,统计两个数组元素之和,和出现的次数,放到 ...

  6. 实现简单的`Blazor`低代码

    本篇博客只实现基本的低代码,比如新增组件,动态修改组件参数 创建项目 首先创建一个空的Blazor Server,并且命名LowCode.Web 实现我们还需要引用一个Blazor组件库,由于作者用M ...

  7. NuGet私有服务器ProGet Docker搭建和公司中实战用法

    一.什么时候需要用到NuGet私有服务器 很多公司中架构师会搭建一个统一的项目基础架构模板,然后全部新项目都会拿这个基础架构来开发新的项目,那架构中就会有很多的中间件,比喻公司内部的封装好的Redis ...

  8. 调用后台接口实现Excel导出功能以及导出乱码问题解决

    实现效果 在导出表格数据的时候,通常分为两种情况 页面列表数据导出 接口返回数据导出 这里主要介绍接口返回数据导出,关于页面的列表数据导出,请看另一篇:vue3+element表格数据导出 接口返回数 ...

  9. 网页怎样引入本地硬盘上的JS文档

    网页通过<script>标记可以引入在线的js文档,只有把网页保存在本地硬盘才能使用相对路径引入本地js文档,普通浏览器难以实现在线页面上引入本地js文档.怎么解决这个问题呢? 首先准备好 ...

  10. php使用PDO获取结果集的方法

    php使用PDO获取结果集的方法  转载:https://www.jb51.net/article/105797.htm 更新时间:2017年02月16日 11:11:42   作者:水晶依恋     ...