Java源码解析ConcurrentHashMap的初始化

 更新时间:2019-01-08 13:00:02   作者:佚名   我要评论(0)

首先看一下代码


private final Node<K,V>[] initTable() {
Node<K,V>[] tab; int sc;
while ((tab = table) == null || tab.length == 0) { // 第一

首先看一下代码

private final Node<K,V>[] initTable() {
    Node<K,V>[] tab; int sc;
    while ((tab = table) == null || tab.length == 0) { // 第一次检查
      if ((sc = sizeCtl) < 0)
        Thread.yield(); // lost initialization race; just spin
      else if (U.compareAndSwapInt(this, SIZECTL, sc, -1)) {
        try {
          if ((tab = table) == null || tab.length == 0) {// 第二次检查
            int n = (sc > 0) ? sc : DEFAULT_CAPACITY;
            @SuppressWarnings("unchecked")
            Node<K,V>[] nt = (Node<K,V>[])new Node<?,?>[n];
            table = tab = nt;
            sc = n - (n >>> 2);
          }
        } finally {
          sizeCtl = sc;
        }
        break;
      }
    }
    return tab;
  }

ConcurrentHashMap在初始化时,如何进行多线程间的同步?

ConcurrentHashMap在初始化时,首先会判断,哈希表是否已经初始化了。如果没有,则尝试进行初始化。

首先会判断sizeCtl的值。sizeCtl是用于多线程之间同步的一个互斥变量。当sizeCtl < 0时,表示已经有线程正在初始化哈希表或哈希表正在扩容,此时,不能再进行操作。

此处sizeCtl其实是实现了自旋锁的功能。自旋锁,即,获取锁失败时,让出CPU,稍后再进行尝试,重复这个过程,直到获得到锁为止。让出CPU的动作,是通过java中的Thread.yield()来实现的。在学校学习java的时候曾经接触过线程的这个方法,但当时不明白什么场景下会用到。原来,Thread.yield()方法可以用来实现自旋锁。

这里,可以提出一个问题,自选锁方式和死循环方式来判断sizeCtl的值,有什么不同?

当然是效率的不同。死循环时,程序会频繁读取sizeCtl的值,在满足条件之前,会浪费很多CPU周期。而自选锁的效率更高,因为当它判断sizeCtl不满足条件时,会主动让出CPU,此时,当前线程会处于ready状态,等待下一次被处理器选中并执行的机会。在这段时间里,其他的线程得以利用CPU周期。所以,自旋锁的效率更高。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对脚本之家的支持。如果你想了解更多相关内容请查看下面相关链接

您可能感兴趣的文章:

  • java中ConcurrentHashMap的读操作为什么不需要加锁
  • Java并发系列之ConcurrentHashMap源码分析
  • java基于ConcurrentHashMap设计细粒度实现代码
  • 详谈HashMap和ConcurrentHashMap的区别(HashMap的底层源码)
  • Java concurrency集合之ConcurrentHashMap_动力节点Java学院整理
  • 基于Java并发容器ConcurrentHashMap#put方法解析
  • java 使用ConcurrentHashMap和计数器实现锁
  • Java 中ConcurrentHashMap的实现
  • Java开发中可以防止界面假死的刷新代码
  • Java源码解析之可重入锁ReentrantLock

相关文章

  • Java源码解析ConcurrentHashMap的初始化

    Java源码解析ConcurrentHashMap的初始化

    首先看一下代码 private final Node<K,V>[] initTable() { Node<K,V>[] tab; int sc; while ((tab = table) == null || tab.length == 0) { // 第一
    2019-01-08
  • 说说如何在Vue.js中实现数字输入组件的方法

    说说如何在Vue.js中实现数字输入组件的方法

    我们对普通输入框进行扩展,实现一个可快捷输入数字组件。 首先制定规则: 只能输入数字。 设计两个快捷按钮,可直接在当前值的基础上增 1 或者减 1。
    2019-01-08
  • 利用python和ffmpeg 批量将其他图片转换为.yuv格式的方法

    利用python和ffmpeg 批量将其他图片转换为.yuv格式的方法

    由于跑编码的需要,所以需要制作一个.yuv格式的图片数据集,但是手头只有.jpg格式的,故记录下转换过程。其他图片格式也可以,代码里修改一下就行。 ①安装ff
    2019-01-08
  • Java开发中可以防止界面假死的刷新代码

    Java开发中可以防止界面假死的刷新代码

    代码如下: try { // 创建一个线程 Thread thread = new Thread() { public void run() { int i = 0; while(true){ final long start = Sys
    2019-01-08
  • vue单文件组件lint error自动fix与styleLint报错自动fix详解

    vue单文件组件lint error自动fix与styleLint报错自动fix详解

    问题描述 之前用Vue(多入口打包成多页)的项目,要修改迁移并修改为一个单页应用,且使用Vue脚手架生成项目,要对js,vue,css文件的代码做lint,在修改Webpack配
    2019-01-08
  • JavaScript学习笔记之DOM操作实例分析

    JavaScript学习笔记之DOM操作实例分析

    本文实例讲述了JavaScript学习笔记之DOM操作。分享给大家供大家参考,具体如下: 一、DOM概念 1. "D":Docment,指的是文档 2. “O”:Object,指的是对象,在
    2019-01-08
  • MySQL执行计划的深入分析

    MySQL执行计划的深入分析

    前言 在之前的面试过程中,问到执行计划,有很多童鞋不知道是什么&#63;甚至将执行计划与执行时间认为是同一个概念。今天我们就一起来了解一下执行计划到底是什么
    2019-01-08
  • 对python mayavi三维绘图的实现详解

    对python mayavi三维绘图的实现详解

    网上下载mayavi的官方帮助文档,里面有很多例子,下面的记录都是查看手册后得到的。 http://code.enthought.com/projects/mayavi/docs/development/latex/may
    2019-01-08
  • 一个因@click.stop引发的bug的解决

    一个因@click.stop引发的bug的解决

    问题 在项目页面中使用 element popover,设置trigger='click'时点击外部不会触发自动隐藏,但在 element 官网中是可以正常触发的(官方示例),项目中的菜
    2019-01-08
  • 易语言模拟鼠标点击实现方法

    易语言模拟鼠标点击实现方法

    易语言对于初学者而言是一种非常好学的中文编程语言,能够快速地实现很多功能,全汉语编程,简单易上手,易语言功能强大实用,系统全部自行设计开发,且易语言
    2019-01-08

最新评论