mar*_*hon 2 java concurrency multithreading locking hashmap
我想尽可能避免锁定读取.但这种"感觉"就像是双重检查锁定,即使没有涉及部分初始化的成员.
这是一个很好的结构吗?
private final Map<String, Stuff> stash = new HashMap<String, Stuff>();
public Stuff getStuff(String name) {
if (stash.containsKey(name))
return stash.get(name);
synchronized(stash) {
if (stash.containsKey(name)) {
return stash.get(name);
}
else {
Stuff stuff = StuffFactory.create(name);
stash.put(name, stuff);
return stuff;
}
}
}
Run Code Online (Sandbox Code Playgroud)
不,这个结构不是线程安全的.
假设线程writer正在将某些东西放入地图中,并且必须调整太小的地图.这是在synchronized街区内完成的,所以你可能认为你很好.
在调整大小期间,地图中没有任何内容可以保证.
现在,在同一时间,假设一个线程reader调用getStuff现有元素.这个线程可以直接访问地图,因为它没有synchronized在第一次调用containsKey和时遇到阻塞get.它将找到未定义状态的映射,虽然它只读取,但它访问内容未定义的数据.可能的结果包括:
getStuffnull它不应该返回.getStuff返回预期的Stuff.getStuff返回HashMap调整大小期间实现使用的一些内部对象.getStuff返回一些Stuff与名称无关的其他内容.getStuff 陷入无限循环.这只是一个应该易于理解的明显案例.所以不,当有像ConcurrentHashMapKuava 这样精心设计的类时,不要采取捷径MapMaker.
顺便说一句:containsKey首先调用然后get使用相同的密钥是相当低效的.只需打电话get,保存结果并将其与之比较null.您将在地图中保存一个搜索操作.
| 归档时间: |
|
| 查看次数: |
1321 次 |
| 最近记录: |