【发布时间】:2013-10-17 17:54:58
【问题描述】:
我正在构建一个带有 Map 的小型缓存,其中包含一些数据库查询的缓存结果。假设这个缓存是以线程安全的方式填充的。我的问题是关于此缓存中的条目,即 Result 类型的对象。
考虑以下场景:
线程 1 从缓存中读取并获取一些 Result 对象,称之为 R。 线程 2 想要同一个对象 R 被杀死,所以它调用缓存来杀死对象 R。
看到两个线程如何只持有对对象 R 的引用,有可能对象 R 突然为线程 1 变为空,因为线程 2 已调用杀死它。
如何避免这种情况?当线程从缓存中读取时,我是否应该制作对象 R 的深层副本,以便即使线程 2 杀死缓存,线程 1 仍然能够完成它正在做的事情而不会出现问题?或者有另一种方法吗?我在线程和并发方面的经验并不是最丰富的,所以要温柔......
【问题讨论】:
-
您需要显示整个 Result 类型,因为它对这个问题很重要;一般来说,不可变或正确同步的 Result 就可以了。请记住,object 不能为 null,只能为对象的 reference。如果线程 1 在线程 2 从缓存中逐出 R 之前获取了有效引用,则引用本身仍然有效。
-
这取决于你的杀死机制!如果你只是从他们的 Map 中删除它,那么线程 1 的逻辑不会发生任何事情,因为它持有它的引用,但是如果你修改它(例如通过使其成员无效),那么线程 1 就会遇到问题。
-
您只缓存对对象的引用,因此只要在删除时不更改对象本身就没有问题(如@AmirPashazadeh 所述)。另一件事:如果可能的话,我建议您使用缓存库,例如 EHCache 或 Guava Cache。
-
@ortang 你当然是对的,我只缓存引用。早该想到的……
标签: java caching concurrency thread-safety