Java 为什么我们需要在Hashtable/ConcurrentHashMap的put方法中锁定?

Java 为什么我们需要在Hashtable/ConcurrentHashMap的put方法中锁定?,java,concurrency,Java,Concurrency,我试图理解多线程环境中Hashtable/Concurrent HashMap的功能。我不明白为什么要同步hashtable的put方法 例如,如果有多个线程试图为一个特定的密钥设置值,那么我们需要使用锁,为什么我们不能在没有锁的情况下执行操作?在最坏的情况下,线程将覆盖彼此的数据,这在技术上对我来说似乎是正确的 我错过了什么?为什么我们需要获得锁的发票?这是Hashtable.put的代码(JDK 11): public synchronized V put(K键,V值){ //确保该值不为n

我试图理解多线程环境中Hashtable/Concurrent HashMap的功能。我不明白为什么要同步hashtable的
put
方法

例如,如果有多个线程试图为一个特定的密钥设置值,那么我们需要使用锁,为什么我们不能在没有锁的情况下执行操作?在最坏的情况下,线程将覆盖彼此的数据,这在技术上对我来说似乎是正确的


我错过了什么?为什么我们需要获得锁的发票?

这是Hashtable.put的代码(JDK 11):

public synchronized V put(K键,V值){
//确保该值不为null
如果(值==null){
抛出新的NullPointerException();
}
//确保该键不在哈希表中。
条目选项卡[]=表格;
int hash=key.hashCode();
int index=(hash&0x7FFFFFFF)%tab.length;
@抑制警告(“未选中”)
条目=(条目)选项卡[索引];
for(;entry!=null;entry=entry.next){
if((entry.hash==hash)和&entry.key.equals(key)){
V old=输入值;
entry.value=值;
返老还童;
}
}
加法器(散列、键、值、索引);
返回null;
}
假设它没有同步,如果两个线程在同一个键上调用
put
,并且它们到达调用
addEntry
的行(在遍历所有条目并没有找到一个带有该键的条目之后),会发生什么情况?坏事情可能会发生,例如,对于同一个键,
count
(条目数)字段将增加两次

例如,如果有多个线程试图为一个特定的密钥设置值,那么我们需要使用锁,为什么我们不能在没有锁的情况下执行操作


锁确保哈希表一次只由一个线程更新。如果同时调用2个put,则可能有2个put同时尝试添加相同的键和值,这将导致错误(Hashtable.put是UPSERT而不是UPDATE)。当第一个线程添加了一个键,第二个线程添加了第二个键时,锁定会停止这种情况的发生。

想想当哈希冲突发生时会发生什么
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;
}