java - 为什么或何时 Map.get(..) 需要同步?

标签 java collections concurrency synchronization

这是来自集合的 SynchronizedMap 的代码片段。我的问题不是特定于下面的代码片段 - 而是一个通用问题:为什么 get 操作需要同步?

public V get(Object key) {
    synchronized (mutex) {return m.get(key);}
}

最佳答案

如果您的线程仅从Map获取,则不需要同步。在这种情况下,使用不可变映射来表达这一事实可能是一个好主意,例如 Guava 中的映射。库,这可以保护您在编译时不会意外修改映射。

当多个线程读取和修改映射时,问题就开始了,因为例如的内部结构HashMap Java 标准库的实现并没有为此做好准备。在这种情况下,您可以在该映射周围包裹一个外部序列化层,例如

  • 使用synchronized关键字,
  • 使用 SynchronizedMap 稍微安全一些。 ,因为这样您就不会在需要的地方忘记 synchonized 关键字,
  • 使用 ReadWriteLock 保护 map ,这将允许多个并发读取线程(这很好)
  • 切换到ConcurrentHashMap总共,为多个线程访问做好了准备。

但是回到你最初的问题,为什么首先需要同步:如果不查看类的代码,这有点难以判断。当一个线程中的 putremove 导致存储桶计数发生变化时,它可能会中断,这会导致读取线程看到太多/太少的元素,因为调整大小还没有完成。也许是完全不同的东西,我不知道,而且这并不重要,因为它不安全的确切原因可能会随着新的 Java 版本随时改变。重要的事实只是它不受支持,并且您的代码可能会在运行时以一种或另一种方式崩溃。

关于java - 为什么或何时 Map.get(..) 需要同步?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19336971/

相关文章:

java - 生产者-消费者日志记录服务以不可靠的方式关闭

java - 通过忽略某些元素来提取一组数字的第一次和最后一次出现

java - 第一次调用后如何在 ChildEventListener 中传递 onChildAdded 条件?

javascript - 为什么我的 backbone.js 集合重置只添加了 1 个模型

powershell - 如何从具有包含特定文本的任何属性的集合中选择对象,并且仅输出这些特定属性?

java - Java如何快速比较两个集合在Java中是否完全相同?

c - UNIX 可移植原子操作

multithreading - 乱序执行和重新排序 : can I see what after barrier before the barrier?

java - lucene/hibernate : @FullTextFilterDef not working with FilterFactory

java - 处理两个 JOptionPane showInputDialog 中的 java 取消按钮