concurrenthashmap

Lock handler for arbitrary keys

坚强是说给别人听的谎言 提交于 2019-11-30 01:56:37
I have code which implements a "lock handler" for arbitrary keys. Given a key , it ensures that only one thread at a time can process that(or equals) key (which here means calling the externalSystem.process(key) call). So far, I have code like this: public class MyHandler { private final SomeWorkExecutor someWorkExecutor; private final ConcurrentHashMap<Key, Lock> lockMap = new ConcurrentHashMap<>(); public void handle(Key key) { // This can lead to OOM as it creates locks without removing them Lock keyLock = lockMap.computeIfAbsent( key, (k) -> new ReentrantLock() ); keyLock.lock(); try {

聊聊并发(四)深入分析ConcurrentHashMap

你说的曾经没有我的故事 提交于 2019-11-30 00:46:16
##术语定义## 哈希算法 :是一种将任意内容的输入转换成相同长度输出的加密方式,其输出被称为哈希值。 哈希表 :根据设定的哈希函数H(key)和处理冲突方法将一组关键字映象到一个有限的地址区间上,并以关键字在地址区间中的象作为记录在表中的存储位置,这种表称为哈希表或散列,所得存储位置称为哈希地址或散列地址。 ##线程不安全的HashMap## 因为多线程环境下,使用Hashmap进行put操作会引起死循环,导致CPU利用率接近100%,所以在并发情况下不能使用HashMap。如下代码: final HashMap<String, String> map = new HashMap<String, String>(2); Thread t = new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 10000; i++) { new Thread(new Runnable() { @Override public void run() { map.put(UUID.randomUUID().toString(), ""); } }, "ftf" + i).start(); } } }, "ftf"); t.start(); t.join(); ##效率低下的HashTable容器##

实现 Java 本地缓存(转)

怎甘沉沦 提交于 2019-11-29 23:48:19
转载的内容 缓存,我相信大家对它一定不陌生,在项目中,缓存肯定是必不可少的。市面上有非常多的缓存工具,比如 Redis、Guava Cache 或者 EHcache。对于这些工具,我想大家肯定都非常熟悉,所以今天我们不聊它们,我们来聊一聊如何实现本地缓存。参考上面几种工具,要实现一个较好的本地缓存,平头哥认为要从以下三个方面开始。 1、存储集合的选择 实现本地缓存,存储容器肯定是 key/value 形式的数据结构,在 Java 中,也就是我们常用的 Map 集合。Map 中有 HashMap、Hashtable、ConcurrentHashMap 几种供我们选择,如果不考虑高并发情况下数据安全问题,我们可以选择HashMap,如果考虑高并发情况下数据安全问题,我们可以选择 Hashtable、ConcurrentHashMap 中的一种集合,但是我们优先选择 ConcurrentHashMap,因为 ConcurrentHashMap 的性能比 Hashtable 要好。 2、过期缓存处理 因为缓存直接存储在内存中,如果我们不处理过期缓存,内存将被大量无效缓存占用,这不是我们想要的,所以我们需要清理这些失效的缓存。过期缓存处理可以参考 Redis 的策略来实现,Redis 采用的是定期删除 + 懒惰淘汰策略。 定期删除策略 定期删除策略是每隔一段时间检测已过期的缓存,并且降之删除

Does a ConcurrentHashMap need to be wrapped in a synchronized block?

泄露秘密 提交于 2019-11-29 22:56:14
Do all non-retreival operations on a ConcurrentHashMap ( put() , remove() etc.) need to be wrapped in a synchronized(this) block? I understand that all of these operations are thread-safe, so is there any real benefit/need in doing so? The only operations used are put() and 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); } ... } No, you are losing the benefits of ConcurrentHashMap by doing that. You may as well be

What is the difference between Segment of ConcurrentHashMap and buckets of HashMap theoretically?

妖精的绣舞 提交于 2019-11-29 22:33:05
问题 I understand that in HashMap, the entries (Key, Value) are placed in buckets based on hash(Key.hashCode)--> The index that denotes the bucket location. In case an entry is already placed at that location, there is a linked list created and the new entry (if it has different key --> via equals() method) is placed at the beginning of the linked list. Can i co-relate this concept with that of ConcurrentHashMap, but instead of Buckets, there are Segments upon which individual threads have a lock.

ConcurrentHashMap笔记

无人久伴 提交于 2019-11-29 19:37:26
ConcurrentHashMap 是支持多线程并发操作的哈希表,与 HashTable 相似,不支持 null 的 key 或 value ,方法声明上也遵循了 HashTable 的规范。总体数据结构与 HashMap 类似,都是数组,按 “ 链地址法 ” 哈希具体的值。但 ConcurrentHashMap 内部按 “ 段 ” 来组织 ,每个段对应了一个或多个哈希 entry 。写操作( put , remove 等)都需要加排它锁,而读操作( get )不需要加锁,因此获取的值可能是读操作的中间状态,尤其对( putAll 和 clear ),读操作可能只能获取部分值。 迭代器和 enumeration 返回的是哈希表某个状态,不抛出 ConcurrentModificationException 。迭代器同一时刻只允许一个线程使用。 ConcurrentHashMap 的成员变量有: static final int DEFAULT_INITIAL_CAPACITY = 16; static final float DEFAULT_LOAD_FACTOR = 0.75f; static final int DEFAULT_CONCURRENCY_LEVEL = 16; static final int MAXIMUM_CAPACITY = 1 << 30; static

ConcurrentHashMap实现机制

Deadly 提交于 2019-11-29 19:37:01
Java 内存模型 由于 ConcurrentHashMap 是建立在 Java 内存模型基础上的,为了更好的理解 ConcurrentHashMap,让我们首先来了解一下 Java 的内存模型。 Java 语言的内存模型由一些规则组成,这些规则确定线程对内存的访问如何排序以及何时可以确保它们对线程是可见的。下面我们将分别介绍 Java 内存模型的重排序,内存可见性和 happens-before 关系。 重排序 内存模型描述了程序的可能行为。具体的编译器实现可以产生任意它喜欢的代码 -- 只要所有执行这些代码产生的结果,能够和内存模型预测的结果保持一致。这为编译器实现者提供了很大的自由,包括操作的重排序。 编译器生成指令的次序,可以不同于源代码所暗示的“显然”版本。重排序后的指令,对于优化执行以及成熟的全局寄存器分配算法的使用,都是大有脾益的,它使得程序在计算性能上有了很大的提升。 重排序类型包括: 编译器生成指令的次序,可以不同于源代码所暗示的“显然”版本。 处理器可以乱序或者并行的执行指令。 缓存会改变写入提交到主内存的变量的次序。 内存可见性 由于现代可共享内存的多处理器架构可能导致一个线程无法马上(甚至永远)看到另一个线程操作产生的结果。所以 Java 内存模型规定了 JVM 的一种最小保证:什么时候写入一个变量对其他线程可见。

jdk源码(二):你知道ConcurrentHashMap的具体实现细节吗?

白昼怎懂夜的黑 提交于 2019-11-29 19:35:28
1、首先抛出几个问题(文章最后有答案): a、ConcurrentHashMap在put的时候,key经过几次hash计算? b、segment 会增大吗? c、新的值是放在链表的表头还是表尾? 2、ConcurrentHashMap是如何存储数据的? 先看图: 从图中我们可以看出ConcurrentHashMap有两个种数据结构:数组和单向链表 那ConcurrentHashMap和如何存放一对key和value呢? put的具体过程: a、根据key计算hash值 b、根据hash值找到segment数组的下标 c、根据上面的下标获取tab数组, d、根据hash值,获取tab数组的下标 c、如果tab当前下标位置上没有值,就直接把存储有key和value的HashEntry存放在tab的当前下标下,否则就是形成一个链表(解决了Hash值冲突) 这就是整个put的大概过程。 是不是有小伙伴说,裤子都脱了,你给我看这个?哈哈哈哈哈,好,上代码 public V put(K key, V value) { Segment<K,V> s; if (value == null) throw new NullPointerException(); int hash = hash(key); // 根据key获取hash值 int j = (hash >>> segmentShift) &

Java容器源码分析-高并发处理Map-ConcurrentHashMap和HashTable

徘徊边缘 提交于 2019-11-29 19:35:14
上一章节,分析了常用的Map集合,随着互联网多线程并发的场景越来越多,原始的数据结构已经无法满足真是的场景需求,所以这种线程安全的集合就显得非常重要。这里介绍一下ConcurrentHashMap和HashTable两种线程安全的数据集合。 那么在分析之前我们首先提出一个问题ConcurrentHashMap和HashTable在做线程安全时的区别? 这里介绍一个比较全面分析源码的帖子:http://blog.csdn.net/zhangerqing/article/details/8193118 总结: 1、HashTable与HashMap采用的数据结构一致。只不过HashTable是线程安全的,在主要的操作方法上都实现了synchronized同步 2、HashTable不允许null的key值存储,如果存储后会报NullPointerException异常 3、ConcurrentHashMap是线程安全的HashMap 4、HashTable和ConcurrentHashMap的区别在于实现锁的机制不一样,ConcurrentHashMap锁的是哈希表中的key,而HashTable锁的是整个哈希表,如下图(侵删) 来源: oschina 链接: https://my.oschina.net/u/3196846/blog/1553508

集合——Hashtable与ConcurrentHashMap区别

帅比萌擦擦* 提交于 2019-11-29 19:34:49
http://www.importnew.com/15845.html ConcurrentHashMap融合了hashtable和hashmap二者的优势。 hashtable是做了同步的,hashmap未考虑同步。所以hashmap在单线程情况下效率较高。hashtable在的多线程情况下,同步操作能保证程序执行的正确性。 hashtable采用synchronized关键字进行同步,每次同步执行的时候都要锁住整个结构 。看下图: (程序使用一个公共锁同步每个方法,并严格地限制只能有一个线程可以同时访问容器——《java并发编程实践》) ConcurrentHashMap正是为了解决这个问题而诞生的。 ConcurrentHashMap锁的方式是稍微细粒度的。 ConcurrentHashMap将hash表分为16个桶(默认值),诸如get,put,remove等常用操作只锁当前需要用到的桶。 (ConcurrentHashMap使用地是更加细化的锁机制,分离锁。任何数量的读线程可以并发访问Map,读者和写着可以并发访问Map,并且有限数量的写线程可以并发修改Map——《java并发编程实践》 ) 试想,原来 只能一个线程进入,现在却能同时16个写线程进入(写线程才需要锁定,而读线程几乎不受限制,之后会提到),并发性的提升是显而易见的。 (1)