繁体   English   中英

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

[英]Why do we need lock in the put methods of Hashtable/ConcurrentHashMap?

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

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

我在这里缺少什么? 为什么我们需要使用锁?

这是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;
}

假设它没有同步,如果两个线程在同一个键上调用put ,并且它们到达调用addEntry的行(在循环所有条目并且没有找到带有键的条目之后)会发生什么? 可能会发生不好的事情,例如,对于同一个键,字段count (条目数)将增加两次。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM