并发读写缓存实现机制(一):为什么ConcurrentHashMap可以这么快?
大家都知道ConcurrentHashMap的并发读写速度很快,但为什么它会这么快?这主要归功于其内部数据结构和独特的hash运算以及分离锁的机制。做游戏性能很重要,为了提高数据的读写速度,方法之一就是采用缓存机制。因此缓存的性能直接影响游戏的承载量和运行流畅度,作为核心基础设施,缓存必须具备以下方面的功能:
1.ConcurrentHashMap的数据结构

|
1
2 3 4 5 6 |
static final class HashEntry<K, V> {
final K key; final int hash; volatile AbsReference value; final HashEntry<K, V> next; } |
|
1
2 3 4 5 6 7 |
static final class Segment extends ReentrantLock implements Serializable {
transient volatile int count; transient int modCount; transient int threshold; transient volatile AtomicReferenceArray<HashEntry> table; final float loadFactor; } |
2.Hash运算的妙用
位运算定位数据在某数组中下标
3.ConcurrentHashMap中数据的定位
|
1
2 3 4 5 6 7 8 9 10 |
private static int hash(int h) {
// Spread bits to regularize both segment and index locations, // using variant of single-word Wang/Jenkins hash. h += (h << ) ^ 0xffffcd7d; h ^= (h >>> ); h += (h << ); h ^= (h >>> ); h += (h << ) + (h << ); ); } |
|
1
2 3 4 |
final Segment<K, V> segmentFor(int hash) {
// 这里的segmentMask就是数组长度-1 return segments[(hash >>> segmentShift) & segmentMask]; } |
|
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
AbsReference get(String key, int hash, CacheLoader<String, AbsReference> loader, boolean isLoad) {
final StopWatch watch = new Slf4JStopWatch(); try { ) { // 先看看数量是否大于0 HashEntry e = getEntry(key, hash); if (e != null) { // 这里只是一次无锁情况的快速尝试查询,如果未查询到,会在有锁情况下再查一次 AbsReference value = getLiveValue(key, hash, now()); watch.lap("cache.getLiveValue()"); if (value != null) { recordAccess(e); return value; } } } if (isLoad) { // 对象为null或者对象已过期,则从在锁的情况下再查一次,还没有则从DB中加载数据 AbsReference ref = lockedGetOrLoad(key, hash, loader); watch.lap("cache.lockedGetOrLoad()"); return ref; } } finally { postReadCleanup(); watch.stop("cache.get()"); } return null; } |
|
1
2 3 4 5 6 7 8 |
HashEntry getEntry(String key, int hash) {
// 首先拿到链头HashEntry,然后依次查找整个entry链 for (HashEntry e = getFirst(hash); e != null; e = e.next) { if (e.hash == hash && key.equals(e.key)) { return e; } } return null; } |
|
1
2 3 4 |
HashEntry<K, V> getFirst(int hash) {
AtomicReferenceArray<HashEntry> tab = table; return tab.get(hash & (tab.length() - 1)); } |
总结
并发读写缓存实现机制(一):为什么ConcurrentHashMap可以这么快?的更多相关文章
- 探索 ConcurrentHashMap 高并发性的实现机制--转
ConcurrentHashMap 是 Java concurrent 包的重要成员.本文将结合 Java 内存模型,来分析 ConcurrentHashMap 的 JDK 源代码.通过本文,读者将了 ...
- 【转】探索 ConcurrentHashMap 高并发性的实现机制
原文链接:https://www.ibm.com/developerworks/cn/java/java-lo-concurrenthashmap/ <探索 ConcurrentHashMap ...
- Qunar机票技术部就有一个全年很关键的一个指标:搜索缓存命中率,当时已经做到了>99.7%。再往后,每提高0.1%,优化难度成指数级增长了。哪怕是千分之一,也直接影响用户体验,影响每天上万张机票的销售额。 在高并发场景下,提供了保证线程安全的对象、方法。比如经典的ConcurrentHashMap,它比起HashMap,有更小粒度的锁,并发读写性能更好。线程安全的StringBuilder取代S
Qunar机票技术部就有一个全年很关键的一个指标:搜索缓存命中率,当时已经做到了>99.7%.再往后,每提高0.1%,优化难度成指数级增长了.哪怕是千分之一,也直接影响用户体验,影响每天上万张机 ...
- Redis 的缓存淘汰机制(Eviction)
本文从源码层面分析了 redis 的缓存淘汰机制,并在文章末尾描述使用 Java 实现的思路,以供参考. 相关配置 为了适配用作缓存的场景,redis 支持缓存淘汰(eviction)并提供相应的了配 ...
- php中并发读写文件冲突的解决方案
在这里提供4种高并发读写文件的方案,各有优点,可以根据自己的情况解决php并发读写文件冲突的问题. 对于日IP不高或者说并发数不是很大的应用,一般不用考虑这些!用一般的文件操作方法完全没有问题.但如果 ...
- php中并发读写文件冲突的解决方案(文件锁应用示例)
PHP(外文名: Hypertext Preprocessor,中文名:“超文本预处理器”)是一种通用开源脚本语言.语法吸收了C语言.Java和Perl的特点,入门门槛较低,易于学习,使用广泛,主要适 ...
- 使用Spring提供的缓存抽象机制整合EHCache为项目提供二级缓存
Spring自身并没有实现缓存解决方案,但是对缓存管理功能提供了声明式的支持,能够与多种流行的缓存实现进行集成. Spring Cache是作用在方法上的(不能理解为只注解在方法上),其核心思想是 ...
- 艺多不压身 -- 常用缓存Cache机制的实现
常用缓存Cache机制的实现 缓存,就是将程序或系统经常要调用的对象存在内存中,以便其使用时可以快速调用,不必再去创建新的重复的实例. 这样做可以减少系统开销,提高系统效率. 缓存主要可分为二大类: ...
- 【Java 并发】Executor框架机制与线程池配置使用
[Java 并发]Executor框架机制与线程池配置使用 一,Executor框架Executor框架便是Java 5中引入的,其内部使用了线程池机制,在java.util.cocurrent 包下 ...
随机推荐
- 前端JavaScript规范
前端JavaScript规范 http://www.imooc.com/article/1402 http://greengerong.com/blog/2015/05/09/qian-duan-ja ...
- HYPER V 文件共享 复制文件 共享硬盘 来宾服务
虚拟机的设置 --> 集成服务 –> 来宾服务 勾选 文件就可以在本地机器和虚拟机上来回复制了. 他可让 Hyper-V 管理员在运行虚拟机的同时将文件复制到虚拟机,且无需使 ...
- Chrome Devtools简介
Chrome开发工具(又称DevTools),是一套内嵌在chrome浏览器内部的web编写和调试工具.DevTools提供给web开发人员深入地访问浏览器内部和web应用的机会.DevTools可以 ...
- 控制HTML Input只能输入数字和小数点
本文介绍两种控制在<input type="text" name="name" value="0" />中只允许输入数字和小数点 ...
- 创建COM对象时遭遇 800702e4
SolidEdge st5(x64) SDK /vs2012/win8.1 x64 西夏普创建SEApplication COM对象时遭遇800702e4.翻来覆去的调vs进程的权限,调se进程的权限 ...
- MyEclipse、Eclipse复制web项目
假设现在已经有一个Java Web项目 ProjectA,现在想做另外一个项目ProjectB,它里面绝大部分功能和结构都可以复用ProjectA中的: 我们就可以通过复制项目的方法来做,具体步骤如下 ...
- 升级Dell的R810固件版本
1.到下面链接去下载win32版本的EXE固件 http://www.dell.com/support/home/cn/zh/cndhs1/Drivers/DriversDetails?driverI ...
- TIOBE Index for January 2016(转载)
Java has won the TIOBE Index programming language award of the year. This is because Java has the la ...
- jQuery整体架构源码解析(转载)
jQuery整体架构源码解析 最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性, ...
- OKHttp的容易使用
OKHttp的简单使用 一方面,最近关于OKHttp的讨论甚嚣尘上,另一方面,我最近也更新了android6.0,发现在6.0中HttpClient不能使用了,于是决定抽时间也看一下OKHttp,总结 ...