java - Java中并发Cache的修改

标签 java caching concurrency thread-safety

我正在使用 Map 构建一个小型缓存,其中保存某些数据库查询的缓存结果。假设该缓存以线程安全的方式填充。我的问题是关于此缓存中的条目,即 Result 类型的对象。

考虑以下场景:

线程 1 从缓存中读取并获取一些 Result 对象,称之为 R。 线程 2 希望杀死同一个对象 R,因此它调用缓存来杀死对象 R。

看看两个线程如何只保存对对象 R 的引用,有可能线程 1 的对象 R 突然变为 null,因为线程 2 已调用杀死它。

如何避免这种情况?当线程从缓存中读取数据时,我是否应该对对象 R 进行深层复制,以便即使线程 2 终止缓存,线程 1 仍然能够顺利完成其正在执行的操作?或者还有另一种方法吗?我在线程和并发方面的经验并不是最丰富的,所以要温柔......

最佳答案

是的——通常您将 Result 视为值对象。线程 2 会将其从缓存中删除/或用更新的值覆盖缓存,但通常不会损坏/破坏 R 的内部状态

线程 2“将 null 放入缓存”或“将新值放入缓存”本身不会影响使用 R 的任何其他引用或线程。R 中的任何内容都不会破​​坏,除非您专门破坏它。从缓存请求对象的代码将不再获得对 R 的特定引用。

指针/或引用将更改或设置为 null,但 R 本身的状态和字段不会。

这假设 R 不持有需要释放的资源..

如果 R 确实需要保存资源(这不是通常的情况),那么您可能需要添加一个使用中计数器并对正在使用的资源进行计数通过保存在缓存中并由客户端代码使用,这样 R 的资源仅在计数器递减至零时才被释放。

但这将是一个不寻常的要求。

关于java - Java中并发Cache的修改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19423093/

相关文章:

java - 使用Java应用程序录制时录制音频样本的时间戳

java - 用于业务逻辑和数据库连接的 Junit Spring Boot 单元测试

java - 缓存不适用于 Spring 3.0、Hibernate 3.6 和 EhCache 2.6.6

java - 如何防止多次同时加载非缓存值?

go - 并发示例的值不正确

java - AES 加密 - 以后如何解密加密的字符串?

facebook - 如何清除 Facebook 的图像缓存

concurrency - BSD/Posix插槽可重入吗?

swift - 并发队列中的 DispatchQueue 同步与同步屏障

java - 将 galen 与 appium 集成并获取 org.openqa.selenium.WebDriverException : Method is not implemented