【发布时间】:2014-01-03 07:37:29
【问题描述】:
我有一个任务来同步HashMap 的方法put(K key, V value)。但它应该比synchronized(this) 或synchronized(table) 运行得更快。我写了这段代码:
public V put(K key, V value) {
if (key == null)
return putForNullKey(value);
int hash = hash(key.hashCode());
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
synchronized(e) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
}
modCount++;
addEntry(hash, key, value, i);
return null;
}
问题是当我通过不同的线程使用相同的键调用此方法时,可能会出现map.entrySet().size() > 1 的情况。所以我的同步是错误的,但我不明白为什么。我怎样才能正确地做到这一点?
【问题讨论】:
-
喜欢..ConcurrentHashMap?
-
我无法使用它。这是一种教育任务。 A 必须同步普通的 HashMap,但它应该比 Collections.synchronizedMap(hashMap);
-
你说的“情况,那个map.entrySet().size() > 1”和“同步出错”是什么意思,能详细点或者举例吗?
-
如果
table.length没有改变(标准HashMap确实改变了这一点),那么同步每个桶的访问(不仅仅是条目)将允许多个线程同时从不同的桶添加/读取时间。这将比锁定整个表有很大的改进,因为“好”(大小正确,具有均匀分布散列值的对象,..)散列表不会多次使用同一个存储桶,也不会在最坏的情况下使用几次。或者锁定存储桶的较小区域(称为条带锁定 AFAIK)。 -
因为这是一项教育任务。也许您的教授甚至不知道他的问题的复杂性。请提供您的导师的解决方案。我真的很感兴趣。
标签: java multithreading hashmap synchronized