首页 > 其他分享 >怎样用读写锁快速实现一个缓存?

怎样用读写锁快速实现一个缓存?

时间:2022-09-28 11:00:45浏览次数:52  
标签:缓存 get 读写 rwl key final 怎样

1)SDK已经有管程了,不是可以解决所有的并发问题的吗,为什么还要有读写锁?

  • 不同的场景下使用不同的锁效果是不一样的,我们的读写锁用在读多写少的场景下那是非常有用的。

2)读写锁是我们JAVA特有的吗?他有什么原则?

  • 读写锁并不是java特有的,是通用的一个技术方案。读写锁的话有三个基本原则:
  • 同一时刻,允许多个线程去读一个变量
  • 同一时刻,只允许一个线程去写变量
  • 当有一个线程在写变量的时候,是不能读的

3)读写锁在java中是怎样实现的,怎样使用?

  • ReadWriteLock他只是一个接口,他的实现子类是ReentrantReadWriteLock。
  • 用的时候直接调用读锁或者写锁readLock()

4)既然说了读写锁适合我们缓存的场景下的使用,那读写锁怎样快速的实现一个缓存呢?

  • 我们定义一个类,这个类呢有k 和 v变量,代表缓存的key和value。有get()读方法,和put()写方法。读的时候上读锁,写的时候上写锁。
class Cache<K,V> {
final Map<K, V> m =
new HashMap<>();
final ReadWriteLock rwl =
new ReentrantReadWriteLock();
// 读锁
final Lock r = rwl.readLock();
// 写锁
final Lock w = rwl.writeLock();
// 读缓存
V get(K key) {
r.lock();
try { return m.get(key); }
finally { r.unlock(); }
}
// 写缓存
V put(K key, V value) {
w.lock();
try { return m.put(key, v); }
finally { w.unlock(); }
}
}

5)实现缓存,会存在数据初始化的问题,那么我们缓存里面的数据该怎样初始化呢?

  • 对于数据比较少的,我们直接一次性把数据装进缓存,简单粗暴又高效。
  • 对于数据比较多的,要读数据的时候,我们再把它存进缓存里面来。

6)上面实现初始化缓存数据的的方法中,第二种代码是怎样实现的?


class Cache<K,V> {
final Map<K, V> m =
new HashMap<>();
final ReadWriteLock rwl =
new ReentrantReadWriteLock();
final Lock r = rwl.readLock();
final Lock w = rwl.writeLock();

V get(K key) {
V v = null;
//读缓存
r.lock(); ①
try {
v = m.get(key); ②
finally{
r.unlock(); ③
}
//缓存中存在,返回
if(v != null) { ④
return v;
}
//缓存中不存在,查询数据库
w.lock(); ⑤
try {
//再次验证
//其他线程可能已经查询过数据库
v = m.get(key); ⑥
if(v == null){ ⑦
//查询数据库
v=省略代码无数
m.put(key, v);
}
finally{
w.unlock();
}
return v;
}
}

7)为什么要再次进行验证?

  • 因为我们的读是并发的,不确定其它线程在这个期间读过没有,为了防止重复读,所以要再次验证。

注意:我们的读写锁是可以升级和降级的。但是java中是不可以升级的,升级的话会造成死锁的现象发生。

标签:缓存,get,读写,rwl,key,final,怎样
From: https://blog.51cto.com/u_15810109/5718757

相关文章

  • 读多写少的场景下,竟然还有比读写锁更牛X的锁?
    1)上一篇文章我们聊了读写锁,他的适用场景是读多写少的场景下,那有没有其它性能比读写锁还要牛逼的锁呢?StampedLock,java1.8诞生的。2)StampedLock比读写锁牛在什么地方?读写锁......
  • elelment中el-cascader怎样自定义显示的lable 与value
    1、后端返回的数据类型  2、页面代码  3、重点在于 :props="{value:'id',label:'className',children:'childNode'}"  ......
  • 关于TE的缓存清理
        TE二次开发的程序,在网络版应用的情况下,不管是CS和BS程序,在服务器端发布数据,有时发现在服务器端数据更新了的情况下,客户端的数据并没有变过来,不管是地形数据,还是......
  • 驱动开发:内核CR3切换读写内存
    首先CR3是什么,CR3是一个寄存器,该寄存器内保存有页目录表物理地址(PDBR地址),其实CR3内部存放的就是页目录表的内存基地址,运用CR3切换可实现对特定进程内存地址的强制读写操作......
  • Java多线程内存读写 —— 内存屏障的理解
    在现代计算机中,CPU往往都是多核的,而由于每个CPUCore中都有自己的高速缓存Cache,因此就会造成内存数据读写的不一致性,表现为 ​​指令乱序​​​ 与 ​​不可见性​​​ ......
  • MyBatis 的缓存处理
    作为常见的ORM框架,在使用MyBatis的过程中可以针对相关的查询进行缓存处理以提高查询的性能。本文将简要介绍一下MyBatis中默认的一级缓存和二级缓存,以及自定义缓存的......
  • 微信小程序中图片链接缓存问题如何解决
    背景描述:更换阿里云上面的图片库,打开小程序后,发现界面展示的图片还是旧图片。原因:是由于缓存导致的。解决方案:1.可以给对象存储OSS设置资源的HTTP响应头即可......
  • odoo 上传的文件怎样保存
    路由@http.route('/web/binary/upload_attachment',type='http',auth="user")@serialize_exceptiondefupload_attachment(self,callback,model,id,......
  • vba读写json文件
    '''VBA-JSONv2.3.1'(c)TimHall-https://github.com/VBA-tools/VBA-JSON''JSONConverterforVBA''Errors:'10001-JSONparseerror''@classJsonC......
  • MyCAT实现MySQL读写分离
    MySQL中间件:用户连接到MySQL的中间件(代理),中间件接收用户的访问转发给后端的mysql数据库。MyCat:是MySQL的一个中间件软件,Mycat是一个开源的分布式数据库系统,是一个实现......