当前位置: 首页 > 知识库问答 >
问题:

Guava Cache,如何在进行删除时阻止访问

葛胡媚
2023-03-14

我有一个线程A,在Guava缓存中插入一个新元素,由于大小策略,缓存将退出与键Y关联的元素。

不幸的是,Y的移除过程R需要很长时间,在Y被R处理的过程中(已经被逐出,但仍在R中),另一个线程B试图获取与密钥Y相关的数据。

基本上,R将尝试为键Y更新数据库,而当该值未更新时,线程B尝试访问数据库以获取与键Y关联的值,该值仍然是旧值。

问题是:在R执行其工作时,如何阻止线程B使用键Y访问元素?

共有1个答案

吕翰飞
2023-03-14

您提到了番石榴缓存,但没有代码示例,所以我给出了一个一般性的答案。

对于以下内容,我假设您有一个“加载缓存”模式,即“自填充缓存”模式。

解决方案1:正确设计缓存交互和数据库事务。

一旦在缓存项上启动事务,更新过程就会使其失效。

  begin transaction
  touch some of the entry data with SQL UPDATE to have it in the transaction
  remove the entry from the cache
  ....
  now you can do more operations on the database regarding the entry data
  if you have the proper isolation level, reads from the database will stall
  until the transaction is committed
  ....
  end transaction

如果从缓存中删除条目,然后启动事务,则会引入竞争条件。

解决方案2:使用缓存来阻止对同一密钥/条目的并发操作。

看看ehcache阻塞缓存。或者看看cache2k,其中阻塞行为是默认的。

但是,您需要自己在加载器级别执行额外的锁定。例如,像下面的例子。

解决方案3:自己在缓存顶部进行锁定,并包装所有缓存操作。比如说:

 Cache cache;
 Lock[] locks = new Lock[16];
 { /* initialize locks */ }

 public Object get(Object key) {
   int idx = key.hashCode() % locks.length;
   locks[idx].lock();
   try { return cache.get(key); 
   } finally { locks[idx].unlock(); }
 }

 public void update(Object key, Object obj) {
   int idx = key.hashCode() % locks.length;
   locks[idx].lock();
   try { return cache.put(key, obj); 
   } finally { locks[idx].unlock(); }
 }

您还可以从ehcache中查看BlockingCache实现,并从中获得一些灵感。

玩得高兴

 类似资料:
  • 问题内容: 我目前正在尝试混淆一系列库。我的基础库包含几个使用类型参数的类和方法,由于Proguard混淆消除了类型参数,其他代码无法使用我的基础库。消除混淆消除了这些问题。我已经阅读了所有ProGuard使用文档,示例和故障排除信息,但无法找到有关如何处理类型参数或ProGuard剥离类型参数的任何文档。 构造函数类型参数问题: 库1包含以下类: 库2包含几个扩展上述类的类,但构造函数会引发编译

  • 问题内容: 强制保持Node.js进程运行的最佳方法是什么,即使其事件循环不为空,从而防止进程终止?我能想到的最好的解决方案是: 如果您将间隔时间保持足够长,它将使间隔运行,而不会引起过多干扰。 有更好的方法吗? 问题的长版 我有一个使用Edge.js来注册回调函数的Node.js脚本,以便可以从.NET中的DLL内部对其进行调用。每秒将调用此功能1次,发送一个应打印到控制台的简单序列号。 Edg

  • 每当我尝试使用axios发送删除endpoint的请求时,都会出现以下错误: 通过CORS策略阻止从源http://localhost:3000在http://localhost:8080/api/payment_card/delete/1234123412343433处访问XMLHttpRequest:对预检请求的响应未通过权限改造检查:请求的资源上不存在“Access-Control-Allo

  • 问题内容: 当从cmd行执行某些命令(比如说“ x”)时,我收到以下消息:“ …按任意键继续…。”。因此,它等待用户输入解除阻止。 但是当我从Java执行相同的命令(’x’)时: 代码块… 我试图在进程的输出流中写入一些内容,但是我该怎么做,以确保代码从未到达该行? 问题答案: 我认为(虽然不能确定)您是在谈论Windows而不是Unix? 如果是这样,则命令行进程实际上可能不是在等待按键(或输入

  • 我试图使用Apache Mina sshd创建一个自定义sftp服务器。到目前为止我的代码: 如您所见,我实现了自己的SFTPEventListener: 多谢帮忙!