作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个静态 HashMap,它将缓存由唯一整数标识的对象;它将从多个线程访问。我将在不同线程中运行多个 HashmapUser
类型的实例,每个实例都希望利用相同的 HashMap(这就是它是静态的原因)。
通常,HashmapUsers
将从 HashMap 中检索。但如果它是空的,则需要从数据库填充它。另外,在某些情况下,HashMap 会被清除,因为它需要数据发生更改并且需要重新填充。
所以,我只是使与 map 的所有交互都同步。但我不确定这是否安全、智能,或者它是否适用于静态变量。
该线程的以下实现安全吗?有任何简化或改进的建议吗?
public class HashmapUser {
private static HashMap<Integer, AType> theMap = new HashSet<>();
public HashmapUser() {
//....
}
public void performTask(boolean needsRefresh, Integer id) {
//....
AType x = getAtype(needsRefresh, id);
//....
}
private synchronized AType getAtype(boolean needsRefresh, Integer id) {
if (needsRefresh) {
theMap.clear();
}
if (theMap.size() == 0) {
// populate the set
}
return theMap.get(id);
}
}
最佳答案
事实上,它绝对不是线程安全的。 HashmapUsers
的每个实例都将使用不同的锁 (this
),这没有任何用处。您必须在同一对象上同步,例如 HashMap 本身。
将 getAtype
更改为:
private AType getAtype(boolean needsRefresh, Integer id) {
synchronized(theMap) {
if (needsRefresh) {
theMap.clear();
}
if (theMap.size() == 0) {
// populate the set
}
return theMap.get(id);
}
}
编辑:请注意,您可以在任何对象上进行同步,前提是所有实例都使用同一对象进行同步。您可以在 HashmapUsers.class
上进行同步,这还允许其他对象锁定对映射的访问(尽管通常最好的做法是使用私有(private)锁)。
因此,只需将 getAtype
方法设置为静态即可,因为隐含的锁现在将是 HashMapUsers.class
而不是 this
。但是,这会暴露您的锁,这可能是也可能不是您想要的。
关于java - 这个HashMap使用线程安全吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32210820/
我是一名优秀的程序员,十分优秀!