gpt4 book ai didi

java - HashMap.remove() 通过在 Key 上使用 String.intern() 同步,这是否有效?或者这是损坏的代码?

转载 作者:搜寻专家 更新时间:2023-11-01 01:51:42 25 4
gpt4 key购买 nike

我最近遇到了以下构造

Map<String,Value> map = new HashMap<>();
...
Value getValue(String key) {
synchronized (key.intern()) {
return map.remove(key);
}
}

鉴于intern() is usually not that fast ,我怀疑这会优于使用 synchronizedCollections.synchronizedMap(Map)ConcurrentHashMap。但即使在这种特殊情况下这种构造比所有其他方法更快:这是否正确同步?我怀疑这是线程安全的,因为在重新组织哈希表时可能会发生删除。但即使这行得通,鉴于HashMap javadoc,我怀疑代码会被破坏。状态:

If multiple threads access a hash map concurrently, and at least one of the threads modifies the map structurally, it must be synchronized externally.

最佳答案

这不足以从多个线程安全地访问 HashMap。事实上,它几乎肯定会破坏某些东西。通过在给定的键上同步,只要不同的线程使用不同的键, map 仍然可以不安全地并发修改。

考虑这三个线程是否试图同时运行:

Thread 1                Thread 2                 Thread 3
synchronized("a") { synchronized("a") { synchronized("b") {
map.remove("a"); map.remove("a"); map.remove("b");
} } }

线程 1 和 2 会正确地相互等待,因为它们在同一个对象上同步(Java 实习生字符串常量)。但是线程 3 不受其他线程中正在进行的工作的阻碍,并立即进入其同步块(synchronized block),因为没有其他线程正在锁定 "b"。现在两个不同的同步块(synchronized block)同时与 map 交互,一切都结束了。不久之后,您的 HashMap 就会损坏。

Collections.synchronizedMap() 正确地使用 map 本身作为同步对象,因此锁定了整个 map ,而不仅仅是正在使用的键。这是防止从多个线程访问的 HashMap 内部损坏的唯一可靠方法。

ConcurrentHashMap 通过内部锁定 map 中所有键的子集,正确地做了我认为您发布的代码试图做的事情。这样,多个线程可以安全地访问不同线程上的不同键,并且永远不会互相阻塞——但如果键恰好在同一个桶中,映射仍然会阻塞。您可以使用 concurrencyLevel 修改此行为构造函数参数。

另请参阅:Java synchronized block vs. Collections.synchronizedMap


顺便说一句,让我们假设 synchronized(key.intern()) 并发访问 HashMap< 的合理方式。这仍然难以置信容易出错。如果应用程序中只有一个地方未能在某个键上调用 .intern(),那么一切都可能崩溃。

关于java - HashMap<String,Value>.remove() 通过在 Key 上使用 String.intern() 同步,这是否有效?或者这是损坏的代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27390281/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com