在多线程环境中将 HashSet 用作非常简单的缓存是否安全?
Is it safe to use HashSet as a very simple cache in a multi-threaded environment?
我知道有类似的 questions/answers,但我似乎找不到我要找的东西。
我正在寻求实现一个内存缓存,它缓存对数据库的调用结果,该数据库正在执行存在性检查。这种存在性检查非常昂贵,一旦对象存在于数据库中,它就永远不会被删除,所以我只需要一个非常简单的内存缓存(甚至是进程内缓存)。调用数据库后,进程会记住该 ID 的存在性检查结果,不应再次调用数据库。
(可能还有一点需要注意的是,如果数据库中不存在该对象,则会创建它)。
我正在为此使用 HashSet (java),并在 check/create 完成后将 ID 添加到集合中,但这是一个高度并发的环境,我不确定HashSet 缺乏线程安全性的影响。
代码仅使用 add() 和 contains() 方法(无迭代)。
我真的不关心这里那里的缓存未命中(以及由此产生的额外数据库调用),但我想知道的是这种 add() 和 contains() 模式是否在集合上被调用在并发线程中可能会导致更多灾难性错误。
您可以使用ConcurrentHashMap进行多线程访问和写入操作。如果只需要 HashSet,可以从 ConcurrentHashMap 派生 ConcurrentHashSet。你可以这样使用。
Set<String> myConcurrentSet = ConcurrentHashMap.newKeySet();
没有。如果要在多线程环境中使用 Map
,请使用 Collections.synchronizedMap(<map object>)
或 ConcurrentHashMap.newKeySet();
:
Set<String> concurrentSet = Collections.synchronizedSet(new HashSet<>());
或...
Set<String> concurrentSet = ConcurrentHashMap.newKeySet();
我知道有类似的 questions/answers,但我似乎找不到我要找的东西。
我正在寻求实现一个内存缓存,它缓存对数据库的调用结果,该数据库正在执行存在性检查。这种存在性检查非常昂贵,一旦对象存在于数据库中,它就永远不会被删除,所以我只需要一个非常简单的内存缓存(甚至是进程内缓存)。调用数据库后,进程会记住该 ID 的存在性检查结果,不应再次调用数据库。
(可能还有一点需要注意的是,如果数据库中不存在该对象,则会创建它)。
我正在为此使用 HashSet (java),并在 check/create 完成后将 ID 添加到集合中,但这是一个高度并发的环境,我不确定HashSet 缺乏线程安全性的影响。
代码仅使用 add() 和 contains() 方法(无迭代)。
我真的不关心这里那里的缓存未命中(以及由此产生的额外数据库调用),但我想知道的是这种 add() 和 contains() 模式是否在集合上被调用在并发线程中可能会导致更多灾难性错误。
您可以使用ConcurrentHashMap进行多线程访问和写入操作。如果只需要 HashSet,可以从 ConcurrentHashMap 派生 ConcurrentHashSet。你可以这样使用。
Set<String> myConcurrentSet = ConcurrentHashMap.newKeySet();
没有。如果要在多线程环境中使用 Map
,请使用 Collections.synchronizedMap(<map object>)
或 ConcurrentHashMap.newKeySet();
:
Set<String> concurrentSet = Collections.synchronizedSet(new HashSet<>());
或...
Set<String> concurrentSet = ConcurrentHashMap.newKeySet();