【问题标题】:Does map need to be synchronized if for each entry only one thread is accessing it?如果每个条目只有一个线程在访问它,是否需要同步映射?
【发布时间】:2012-11-23 10:13:41
【问题描述】:

我有一张地图。让我们说:

Map<String, Object> map = new HashMap<String, Object>();

多个线程正在访问此映射,但是每个线程仅访问映射中自己的条目。这意味着如果线程 T1 将对象 A 插入到映射中,则可以保证没有其他线程将访问对象 A。最后线程 T1 也会删除对象 A。

也保证没有线程会遍历地图。

这张地图需要同步吗?如果是,您将如何同步它? (ConcurrentHashMap、Collections.synchronizedMap() 或同步块)

【问题讨论】:

  • 是的,问题在于冲突和多线程添加,两个线程可能想要插入相同的哈希而不看到冲突,这可能是个问题。
  • 是否有任何线程迭代地图?还是只是简单的 put() get() ?

标签: java multithreading concurrency


【解决方案1】:

是的,您需要同步或并发映射。想想地图的大小:两个线程可以并行添加一个元素,并且都增加大小。如果您不同步地图,您可能会遇到竞争条件,这会导致大小不正确。还有很多其他事情可能会出错。

但是您也可以为每个线程使用不同的映射,不是吗?

ConcurrentHashMap 通常比同步的 HashMap 更快。但选择取决于您的要求。

【讨论】:

  • 能否请您详细说明一下ConcurrentHashMap 通常比同步的HashMap 更快。但是选择取决于您的要求。:在任何情况下旧式外部同步 Map 比 ConcurrentHashMap 有任何优势?
【解决方案2】:

如果您确定每个线程只有一个条目,并且没有线程迭代/搜索地图,那么为什么需要地图?

您可以改用ThreadLocal 对象,该对象将包含特定于线程的数据。如果您需要保留字符串-对象对,可以为该对创建一个特殊的类,并将其保存在ThreadLocal 字段中。

class Foo {
   String key;
   Object value;
   ....
}

//below was your Map declaration
//Map<String, Object> map = ...
//Use here ThreadLocal instead
final ThreadLocal<Foo> threadLocalFoo = new ThreadLocal<Foo>();
...
threadLocalFoo.set(new Foo(...));
threadLocalFoo.get() //returns your object
threadLocalFoo.remove() //clears threadLocal container

您可以在ThreadLocal javadocs 中找到有关 ThreadLocals 的更多信息。

【讨论】:

    【解决方案3】:

    我会说是的。获取数据不是问题,添加数据才是问题。

    HashMap 有一系列桶(列表);当你把数据放到HashMap时,hashCode用来决定item去哪个bucket,然后item被添加到list中。

    因此可能会同时将两个项目添加到同一个存储桶中,并且由于某些运行条件,只有其中一个被有效存储。

    【讨论】:

      【解决方案4】:

      您必须在地图中同步写入操作。如果在初始化映射后,没有线程会插入新条目或删除映射中的条目,则不需要同步它。

      但是,在您的情况下(每个线程都有自己的条目),我建议使用ThreadLocal,它允许您拥有一个“本地”对象,每个线程将具有不同的值。

      希望对你有帮助

      【讨论】:

        【解决方案5】:

        对于这种情况我认为 ConcurrentHashMap 是最好的 Map,因为 Collections.synchronizedMap() 或同步块(基本相同)都有更多的开销。

        如果你想插入条目而不只是在不同的线程中读取它们,你必须同步它们,因为 HashMap 的工作方式。

        【讨论】:

          【解决方案6】:

          - 首先,写Thread-safe code 是一种习惯,特别是在上述情况下,而不是在所有情况下。

          - 最好使用HashTable,即synchronized Mapjava.util.concurrent.ConcurrentHashMap&lt;K,V&gt;

          【讨论】:

          • 不,这并不总是一个好习惯。如果是这样,Vector 就不会被 ArrayList 取代,StringBuffer 不会被 StringBuilder 取代,Hashtable 不会被 HashMap 取代。 Collections.synchronizedMap(new HashMap()) 也应该优先于 Hashtable。
          • 小点:Hash table 不允许 null 但 HashMap 允许。 HashTable => t 小写:)
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-11-12
          • 1970-01-01
          • 1970-01-01
          • 2012-08-18
          • 1970-01-01
          相关资源
          最近更新 更多