写点什么

再来一篇!看 jdk 源码大师亲自操刀编写的集合源码!

  • 2021 年 12 月 05 日
  • 本文字数:1812 字

    阅读完需:约 6 分钟

大家好,我是 tin,这是我的第 8 篇原创文章


这个图拍摄于老家县城一售楼处。作为外出上班的一族,一年 365 天在家的时间常常不超过十天。

在侃技术前,聊一聊自己对家乡变化的感慨。

最大的感慨莫过于,我们县城要通高铁了,以后老家和工作之地的距离将变成 2 小时!想想就觉得这是一件多么幸福的事。

今年过年回家趁着假期和家人又新购置了一套新商品期房,就买高铁站片区边上。

在家买房的最大特点就是,房子面积要大的,动不动都一百多两百平,在深圳这个地方就不敢想啦。

房子本来最早于 2019 年已打算购置,但当时时间仓促没看好,加之 2020 年过年刚好遇上疫情,足不出户,一耽搁就到了 2021 年。

或许刚好是疫情的原因,今年房价特价销售(也就是降价了),相对 2019 年降了 500-1000 元/㎡。在这种七八线城市,房价本就几千块一平,这个降价幅度是异常高的(打心里认为,2021 年是小城购房最佳时机之一)。

其实,这里唠嗑只是想感慨一下小城市的变化之大!但是我们很多人却容易忽略身边最亲近的事与物。比如我,我竟然不知我们县城的政务中心都搬迁了,整个县城南片区规划建设已相当完善,商品房、幼儿园、中小学校区、超宽大道等等随处可见,新医院、新行政办公楼、高铁站等这些似乎在缩小与大城市的差距。

这些年,国家对农村建设力度也很大,肉眼可见的变化常常被我们谈及。普遍被提到的一个变化是路变好了。村村通公路、水泥路,每年外出回家的人一定能感受到。路变好,相应的是,车也就多了。买车的人越来越多,每家都会有一辆代步小轿车。

除了车,家里爸爸妈妈们网上购物更加频繁,比起以往,老人们都可以自行网上购物,自行取快递,这种线上体验的场景规模越来越空大,所以,农村通宽带也已不是什么新鲜事。

朋友们,你们觉得呢,你们家乡还有哪些变化?

ConcurrentHashMap

我们打开 ConcurrentHashMap 源码,类开头鲜明地标着作者:@author Doug Lea

Doug Lea 是谁?以前也有提到过,他是一位大学老师,同时也是世界上对 Java 影响最大的人之一。JDK 源码中 java.util.concurrent 包就是他创作的。

我们找到 jdk1.7 的源码,ConcurrentHashMap 中的 get 方法还能看到 Doug Lea 的代码(下图源码截图基于 jdk7-b147)

我们知道,HashMap 是线程不安全的,并发情况下使用 hashmap 有 cpu 飙升的风险。为了使用线程安全的 HashMap,我们常使用 ConcurrentHashMap。

本文基于 jdk1.7 讲解,所以 concurrenthashmap 还是采用分段锁。

ConcurrentHashmap 默认有 16 个 Segment,最多支持 65536 个 Segment,这是可以通过 ConcurrentHashMap 的构造器指定的。默认情况下 ConcurrencyLevel 等于 16

如果指定 ConcurrencyLevel,最大只能等于 65536

Segment 通过继承 ReentrantLock 来进行加锁,每次锁住一个 segment 来保证每个 Segment 内的操作的线程安全性从而实现全局线程安全。

定位一个元素的过程需要进行两次 Hash 操作,第一次 Hash 定位到 Segment,第二次 Hash 定位到元素所在的链表的头部。看看 get 方法的源码:

ConcurrentHashMap 定义了一个 Segment 数组 segments,Segment 则定义了一个 HashEntry 数组 table。

这种两级定位的结构带来的副作用是 hash 过程要比普通的 HashMap 要长,但是带来的好处是更大的,写操作可以只对元素所在的 Segment 进行加锁即可,不会影响到其他的 Segment,这样,ConcurrentHashMap 可以支持最大 Segment 数量的并发量,吞吐量就比 HashMap 大了很多。

细心的你可能已经发现,代码截图中使用到了 UNSAFE.getObjectVolatile(segments, u),这个是什么意思呢?

getObjectVolatile 是为保证并发访问数组的第 k 个元素可以显式 volatile 读取,为了值的可见性。

说到 Unsafe,这玩意儿咋一看感觉很高大上,因为我们平常编程几乎没见过。但是,Unsafe 现在在 Java 里面是一个“擦边球”,基本处于一个“不推荐使用”的状态。

Unsafe 是位于 sun.misc 包下的一个类,主要提供一些用于执行低级别、不安全操作的方法,如直接访问系统内存资源、自主管理内存资源等。因为可以访问系统资源、可以自主操作内存空间,这无疑增加了程序发生指针问题的风险,Java 的垃圾回收器本来很大一个原因是为了解决这个问题,使用 Unsafe 类会使得程序出错的概率变大,Java 官方也不建议开发者使用它。

R 大有一篇回答,关于 Unsafe,https://www.zhihu.com/question/29266773/answer/43757304

结语

我是 tin,一个在努力让自己变得更优秀的普通攻城狮。自己阅历有限、学识浅薄,如有发现文章不妥之处,非常欢迎加我提出,我一定细心推敲加以修改。


坚持原创不容易,你的正反馈是我坚持输出的最强大动力,谢谢!


发布于: 5 小时前阅读数: 7
用户头像

我是tin,公众号:看点代码再上班。 2018.11.13 加入

我是tin,专职后端开发,在这里分享Java相关知识、我的工作经验和工作思考。坚持原创,持续原创,欢迎关注公众号【看点代码再上班】

评论

发布
暂无评论
再来一篇!看jdk源码大师亲自操刀编写的集合源码!