当前位置: 首页 > 面试题库 >

ConcurrentHashMap是否需要包装在同步块中?

孔欣可
2023-03-14
问题内容

这样做,即ConcurrentHashMap(所有非retreival操作put()remove()等)需要在被包裹synchronized(this)块?我知道所有这些操作都是线程安全的,因此这样做有真正的好处/需要吗?使用的唯一操作是put()remove()

protected final Map<String, String> mapDataStore = new ConcurrentHashMap<String, String>();

public void updateDataStore(final String key, final String value) {
    ...
    synchronized (this) {
        mapDataStore.put(key, value);
    }
    ...
}

问题答案:

不,ConcurrentHashMap这样做会失去您的利益。您也可以使用HashMapwith
synchronizedsynchronizedMap()锁定整个表(这是在中包装操作时要执行的操作synchronized,因为隐含的监视器是整个对象实例。)

目的ConcurrentHashMap是通过允许在表上进行并发读/写而不锁定整个表来提高并发代码的吞吐量。该表通过使用锁条带在内部支持此功能(多个锁而不是一个,每个锁分配给一组散列桶-
请参阅Goetz等人的《实践中的Java并发性》)。

一旦使用ConcurrentHashMap,由于实现中的锁条等,所有标准映射方法(put()remove()等)都成为原子的。唯一的权衡是方法类似size()并且isEmpty()不一定返回准确的结果,因为它们唯一的方法就是所有操作都可以锁定整个表。

ConcurrentMap接口接口还增加了新的原子复合操作,如putIfAbsent()(把东西只有当它的关键是不是已经在地图),remove()同时接受key和value(删除仅当其值等于你传递参数的条目),等等。这些操作过去需要锁定整个表,因为它们需要两个方法调用才能完成(例如,如果使用的是标准实现,则putIfAbsent()需要对containsKey()and进行调用,并且put()包装在一个synchronized块中Map。)再一次,通过使用这些方法,您可以获得更大的吞吐量避免锁定整个表。



 类似资料:
  • 问题内容: 我有一个ConcurrentHashMap,在其中执行以下操作: 我的问题是-是否有必要做多余的事情 检查同步块内部,以便其他线程不会初始化相同的哈希图值? 也许检查是必要的,但我做错了吗?我在做什么似乎有点可笑,但我认为这是必要的。 问题答案: *ConcurrentHashMap上的 *所有 操作都是线程安全的,但是线程安全的操作是不可组合的。您试图使原子操作成为一对操作:检查地图

  • 问题内容: 我有两个线程,我想确保我在LinkedBlockingQueue上正确进行了同步。这正确吗?还是不需要在(messageToCommsQueue)上进行显式同步? 宣言: 方法一: 方法二: 问题答案: 是的,没有必要。JavaDoc说: BlockingQueue实现是线程安全的。

  • 我对同步块有一些疑问。在提问之前,我想分享另一个相关帖子链接的答案,以回答相关问题。我引用彼得·劳里的同一个答案。 > <块引号> 同步确保您对数据有一致的视图。这意味着您将读取最新值,其他缓存将获得最新值。缓存足够智能,可以通过特殊总线相互通信(JLS不需要,但允许)该总线意味着它不必触摸主存储器即可获得一致的视图。 如果您只使用同步,则不需要Volatile。如果您有一个非常简单的操作,而同步

  • 问题内容: 我对同步块几乎没有疑问。 1. > 同步可确保您拥有一致的数据视图。这意味着您将读取最新值,而其他缓存将获得最新值。高速缓存足够智能,可以通过特殊总线相互通信(这不是JLS所必需的,但允许)。该总线意味着不必触摸主内存即可获得一致的视图。 如果仅使用同步,则不需要volatile。如果您有一个非常简单的操作(对于同步操作可能会过分杀伤),则波动性很有用。 参考上面,我有以下三个问题:

  • 问题内容: 这似乎是一个非常基本的问题,但我找不到明确的确认。 假设我有一个本身已正确同步的类: 如果我需要 引用 在线程之间共享的该类的实例, 我仍然需要将该实例声明为volatile或final ,对吗?如: 或者,如果不能是最终的,则因为其实例化取决于其他一些事先未知的条件(与GUI的交互,来自套接字的信息等): final或volatile是强制性的 ,将访问权限同步到其自身成员的事实并不

  • 问题内容: 是用什么包装类之间的差异上,和? 它只是能够在迭代()的同时进行修改吗? 问题答案: 同步: 每种方法都使用对象级锁进行同步。因此,synchMap上的get和put方法获取一个锁。 锁定整个集合是性能开销。当一个线程保持该锁时,其他任何线程都不能使用该集合。 是在JDK 5中引入的。 在对象级别没有锁定,锁定的粒度要好得多。对于,锁定可以处于哈希图存储桶级别。 较低级别的锁定的结果是