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

Java:ConcurrentHashMap(JDK1.8)为什么要使用synchronized而不是如ReentranLock这样的可重入锁?

祁英哲
2023-04-24

我想从下面几个角度讨论这个问题:

(1)锁的粒度

首先锁的粒度并没有变粗,甚至变得更细了。每当扩容一次,ConcurrentHashMap的并发度就扩大一倍。

(2)Hash冲突

JDK1.7中,ConcurrentHashMap从过二次hash的方式(Segment -> HashEntry)能够快速的找到查找的元素。在1.8中通过链表加红黑树的形式弥补了put、get时的性能差距。
JDK1.8中,在ConcurrentHashmap进行扩容时,其他线程可以通过检测数组中的节点决定是否对这条链表(红黑树)进行扩容,减小了扩容的粒度,提高了扩容的效率。

下面是我对面试中的那个问题的一下看法。

为什么是synchronized,而不是ReentranLock

(1)减少内存开销

假设使用可重入锁来获得同步支持,那么每个节点都需要通过继承AQS来获得同步支持。但并不是每个节点都需要获得同步支持的,只有链表的头节点(红黑树的根节点)需要同步,这无疑带来了巨大内存浪费。

(2)获得JVM的支持

可重入锁毕竟是API这个级别的,后续的性能优化空间很小。
synchronized则是JVM直接支持的,JVM能够在运行时作出相应的优化措施:锁粗化、锁消除、锁自旋等等。这就使得synchronized能够随着JDK版本的升级而不改动代码的前提下获得性能上的提升。

 类似资料:
  • 我试图理解,如果可以使用,是什么让并发锁如此重要。在下面的伪代码中,我可以执行以下任一操作: 同步整个方法或同步脆弱区域(

  • 问题内容: 我不确定为什么列出项目时为什么需要使用ul-li而不是简单地使用div。我可以使两者看起来完全一样,因此与创建div相比,创建无序列表的功能优势在哪里? 问题答案: 为了语义正确。HTML具有表达事物列表的功能,它可以帮助Google机器人,屏幕阅读器以及所有不仅仅关心网站外观的用户更好地了解您的内容。

  • 问题内容: 我不明白为什么很少有导入包在“ java”后面附加“ x”。是什么原因?难道就和其他人一样吗? 问题答案: Swing最初是Java的扩展-可单独下载的库。它成为Java 1.2中“主要” JRE的一部分。一个单独的库声称拥有java。*包,这很奇怪,因此是目前的情况。还有许多其他扩展都有类似的故事。 在Swing的维基百科的文章有其历史提供更多的信息。

  • 问题内容: 每当我读到关于使用Scala的作者通常提的是演员,而应使用(此举例)。虽然我大致了解了Actor的工作原理,但我真的很想看到一个Actor的示例,该示例被用来在一段代码中替换Java的方法修饰符(这意味着它的Scala等效项- 块)。例如,修改数据结构的内部将很高兴。 这是对Actor的很好利用,还是我被误导了? 问题答案: Actor保证一次只处理一条消息,这样就不会有两个线程访问任

  • 问题内容: 目前使用jQuery,当我需要在发生点击时做一些事情时,我会像这样… 我正在看别人在项目上有的代码,他们这样做是… 请注意,就我所知,它似乎在做相同的事情,除了它们使用的是live()函数(现在已弃用并且jQuery文档说要使用live()函数),但是无论哪种方式,为什么要使用live / on()而不是我的第一个示例? 问题答案: 因为您可能具有动态生成的元素(例如,来自AJAX调用

  • 问题内容: 在selenium.webdriver.common.by中使用By代替常规的find_element_by _…方法的目的和好处是什么?例如: vs: 问题答案: 据documentatio ñ 似乎是一种“ 私人 所使用的”法的方法和还可以使用页面对象 因此,使用Page Object模式是您可能需要+ 而不是的原因。 例如,您有一些包含元素值的变量 然后用它来定位元素为 如果由于