英文:
Why do we need lock in the put methods of Hashtable/ConcurrentHashMap?
问题
我正在尝试理解在多线程环境中 Hashtable/Concurrent HashMap 的功能。我无法弄清楚为什么要使 Hashtable 的 put
方法同步。
例如,如果有多个线程尝试为特定的键设置值,我们为什么需要使用锁?为什么我们不能在没有锁的情况下执行操作?在最糟糕的情况下,线程将覆盖彼此的数据,从技术上来说这似乎是正确的。
我在这里漏掉了什么?为什么我们需要涉及锁定?
英文:
I am trying to understand the functioning of Hashtable/Concurrent HashMap in multithreaded environment. I can't figure out why make the put
method of hashtable synchronized.
For instance, if there are multiple threads trying to set value for a particular key, we do we need to use locks, why can't we perform the operations without the locks? At worst, the threads will overwrite each other's data, which technically seems right to me.
What am I missing here? Why do we need to get locks invovled?
答案1
得分: 3
这是Hashtable.put
方法的代码(JDK 11):
public synchronized V put(K key, V value) {
// 确保值不为null
if (value == null) {
throw new NullPointerException();
}
// 确保键不已经存在于Hashtable中。
Entry<?,?> tab[] = table;
int hash = key.hashCode();
int index = (hash & 0x7FFFFFFF) % tab.length;
@SuppressWarnings("unchecked")
Entry<K,V> entry = (Entry<K,V>)tab[index];
for(; entry != null ; entry = entry.next) {
if ((entry.hash == hash) && entry.key.equals(key)) {
V old = entry.value;
entry.value = value;
return old;
}
}
addEntry(hash, key, value, index);
return null;
}
假设未进行同步,如果两个线程在相同的键上调用put
方法,并且它们都到达调用addEntry
的那一行(在遍历所有条目并未找到具有相同键的条目之后),会发生什么呢?可能会出现问题,例如,对于相同的键,字段count
(条目数)会增加两次。
英文:
Here is the code of Hashtable.put
(JDK 11):
public synchronized V put(K key, V value) {
// Make sure the value is not null
if (value == null) {
throw new NullPointerException();
}
// Makes sure the key is not already in the hashtable.
Entry<?,?> tab[] = table;
int hash = key.hashCode();
int index = (hash & 0x7FFFFFFF) % tab.length;
@SuppressWarnings("unchecked")
Entry<K,V> entry = (Entry<K,V>)tab[index];
for(; entry != null ; entry = entry.next) {
if ((entry.hash == hash) && entry.key.equals(key)) {
V old = entry.value;
entry.value = value;
return old;
}
}
addEntry(hash, key, value, index);
return null;
}
Assuming it was not synchronized, what happens if two threads are calling put
on the same key, and they reached the line calling addEntry
(after looping over all entries and not finding one with the key)? Bad things may happen, for example, the field count
(number of entries) will be increased twice for the same key.
答案2
得分: 0
例如,如果有多个线程尝试为特定键设置值,我们为什么需要使用锁?为什么不能在没有锁的情况下执行操作?
锁确保哈希表一次只能被一个线程更新。如果同时调用了两次"put"操作,可能会出现两个"put"操作同时尝试在同一时间添加相同的键和值,这将导致错误("Hashtable.put"是"UPSERT"操作,而不是"UPDATE"操作)。锁定可以阻止这种情况发生,因为第一个线程添加一个键,而第二个线程添加另一个键。
英文:
> For instance, if there are multiple threads trying to set value for a particular key, we do we need to use locks, why can't we perform the operations without the locks?
Locks ensure that the hashtable is only updated by one thread at a time. If 2 puts were called concurrently, there could be 2 puts trying to add the same key and value at the same time which would cause an error (Hashtable.put is an UPSERT rather than UPDATE). Locking stops this occurring as one key is added by the first thread and the second key by the second.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论