这是来自集合的 SynchronizedMap
的代码片段。我的问题不是特定于下面的代码片段 - 而是一个通用问题:为什么 get 操作需要同步?
public V get(Object key) {
synchronized (mutex) {return m.get(key);}
}
最佳答案
如果您的线程仅从Map
获取
,则不需要同步。在这种情况下,使用不可变映射来表达这一事实可能是一个好主意,例如 Guava 中的映射。库,这可以保护您在编译时不会意外修改映射。
当多个线程读取和修改映射时,问题就开始了,因为例如的内部结构HashMap
Java 标准库的实现并没有为此做好准备。在这种情况下,您可以在该映射周围包裹一个外部序列化层,例如
- 使用
synchronized
关键字, - 使用
SynchronizedMap
稍微安全一些。 ,因为这样您就不会在需要的地方忘记synchonized
关键字, - 使用
ReadWriteLock
保护 map ,这将允许多个并发读取线程(这很好) - 切换到
ConcurrentHashMap
总共,为多个线程访问做好了准备。
但是回到你最初的问题,为什么首先需要同步:如果不查看类的代码,这有点难以判断。当一个线程中的 put
或 remove
导致存储桶计数发生变化时,它可能会中断,这会导致读取线程看到太多/太少的元素,因为调整大小还没有完成。也许是完全不同的东西,我不知道,而且这并不重要,因为它不安全的确切原因可能会随着新的 Java 版本随时改变。重要的事实只是它不受支持,并且您的代码可能会在运行时以一种或另一种方式崩溃。
关于java - 为什么或何时 Map.get(..) 需要同步?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19336971/