基于ReadWriteLock读写锁实现的缓存
时间:2022-07-24
本文章向大家介绍基于ReadWriteLock读写锁实现的缓存,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
package william.pattern;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.function.Supplier;
/**
* @Author: ZhangShenao
* @Date: 2019/5/22 10:22
* @Description:基于读写锁实现的简单的缓存
* 1.读操作之间可并发执行
* 2.读写、写写操作之间互斥
* 3.根据key获取不同的锁,减小锁粒度
*/
public class SimpleCache<K, V> {
private Map<K, V> cache = new HashMap<>();
private Map<K, ReadWriteLock> locks = new ConcurrentHashMap<>();
public V get(K key, Supplier<V> optionsWhenMiss) {
V value;
try {
//加读锁
acquireLock(key, false);
//查询缓存
value = cache.get(key);
} finally {
//释放读锁
releaseLock(key, false);
}
//如果缓存命中,则直接返回
if (value != null) {
return value;
}
//缓存未命中,加写锁,执行optionsWhenMiss操作
try {
acquireLock(key, true);
//这里再进行一次缓存的查询,避免高并发场景下,多线程竞争写锁,导致数据的重复查询
value = cache.get(key);
if (value == null) {
value = optionsWhenMiss.get();
}
} finally {
//释放写锁
releaseLock(key, true);
}
return value;
}
public void put(K key, V value) {
//加写锁
try {
acquireLock(key, true);
cache.put(key, value);
} finally {
//释放写锁
releaseLock(key, true);
}
}
private void acquireLock(K key, boolean write) {
Lock lock = lockForKey(key, write);
lock.lock();
}
private void releaseLock(K key, boolean write) {
Lock lock = lockForKey(key, write);
lock.unlock();
}
private Lock lockForKey(K key, boolean write) {
ReadWriteLock rw = locks.computeIfAbsent(key, k -> new ReentrantReadWriteLock());
return write ? rw.writeLock() : rw.readLock();
}
}
- Spring Cloud中Hystrix的服务降级与异常处理
- Open vSwitch源码解析之基于VxLAN实现NSH解析功能
- Spring Cloud自定义Hystrix请求命令
- JavaScript面试问题:事件委托和this
- Spring Cloud中的断路器Hystrix
- js的隐含参数(arguments,callee,caller)使用方法
- Spring Cloud中的负载均衡策略
- Spring Cloud中负载均衡器概览
- 没有event loop的PHP
- RestTemplate的逆袭之路,从发送请求到负载均衡
- limit_area_cirle
- Spring RestTemplate中几种常见的请求方式
- 什么是客户端负载均衡
- jQuery 升级踩坑大全
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- linux 上在指定时间段内每隔多少分钟自动执行任务计划crontab
- 详解如何使用Spark和Scala分析Apache访问日志
- Centos 7.4中的远程访问控制的实现方法
- Linux查找特定程序whereis实例详解
- SpringBoot实战(二):SpringMvc接收xml请求
- CentOS环境下安装PHPUnit的方法分析
- Centos下安装Ansible的示例代码
- ubuntu18.04安装搜狗拼音的简易教程
- linux中$符号的基础用法总结
- Linux下的 mariadb 使用 root 用户启动方式(推荐)
- window与linux项目部署之linux文件路径不存在问题
- Ubuntu 18.04安装 pyenv、pyenv-virtualenv、virtualenv、Numpy、SciPy、Pillow、Matplotlib
- Linux使用 iftop 实时监控网卡的流量
- Centos中TCPWrappers访问控制实现
- CentOS7 重新分配分区大小的实现方法