concurrenthashmap

Using ConcurrentHashMap, when is synchronizing necessary?

只愿长相守 提交于 2019-11-28 23:29:05
I have a ConcurrentHashMap where I do the following: sequences = new ConcurrentHashMap<Class<?>, AtomicLong>(); if(!sequences.containsKey(table)) { synchronized (sequences) { if(!sequences.containsKey(table)) initializeHashMapKeyValue(table); } } My question is - is it unnecessary to make the extra if(!sequences.containsKey(table)) Check inside the synschronized block so other threads wont initialize the same hashmap value? Maybe the check is necessary and I am doing it wrong? It seems a bit silly what I'm doing, but I think it is necessary. All operations on a ConcurrentHashMap are thread

HashMap、HashTable 和 ConcurrentHashMap 线程安全问题

大城市里の小女人 提交于 2019-11-28 20:31:00
一、HashMap HashMap 是线程不安全的。 JDK 1.7 HashMap 采用数组 + 链表的数据结构,多线程背景下,在数组扩容的时候,存在 Entry 链死循环和数据丢失问题。 JDK 1.8 HashMap 采用数组 + 链表 + 红黑二叉树的数据结构,优化了 1.7 中数组扩容的方案,解决了 Entry 链死循环和数据丢失问题。但是多线程背景下,put 方法存在数据覆盖的问题。 1.7 中扩容引发的线程不安全分析 void transfer(Entry[] newTable, boolean rehash) { int newCapacity = newTable.length; for (Entry<K,V> e : table) { while(null != e) { Entry<K,V> next = e.next; if (rehash) { e.hash = null == e.key ? 0 : hash(e.key); } int i = indexFor(e.hash, newCapacity); e.next = newTable[i]; newTable[i] = e; e = next; } } } 这段代码是 HashMap 的扩容操作,重新定位每个桶的下标,并采用头插法将元素迁移到新数组中。头插法会将链表的顺序翻转

ConcurrentHashMap分析

一世执手 提交于 2019-11-28 19:22:27
ConcurrentHashMap分析: 闻其名,便知其义,并发的hashmap, 我们先来看看ConcurrentHashMap数据结构图: ConcurrentHashMap由多个Segment组成,而Segment内部是由HashEntry(存放key-value对)数组组成(类似于HashMap的Entry数组)。 从代码来看ConcurrentHashMap的基本属性: //segment掩码值: 用于计算key所在segments索引值 final int segmentMask; //segment偏移值: 用于计算key所在segments索引值 final int segmentShift; //segments数组,其内部也是由HashEntry数组实现,正因为有了多个segment,才提高了并发度 final Segment<K,V>[] segments; 看到重要的Segment数据结构: /** * 其实现了ReentrantLock, 自身可线程安全 * 其本身就像个HashMap */ static final class Segment<K,V> extends ReentrantLock implements Serializable { //存放元素的table transient volatile HashEntry<K,V>[] table

ConcurrentHashMap

◇◆丶佛笑我妖孽 提交于 2019-11-28 19:00:41
ConcurrentHashMap主要有三大结构:整个Hash表,segment(段),HashEntry(节点)。每个segment就相当于一个HashTable。 Base 1.8 抛弃了原有的 Segment 分段锁,而采用了 CAS + synchronized 来保证并发安全性。 (1)HashEntry类 每个HashEntry代表Hash表中的一个节点,在其定义的结构中可以看到,除了value值没有定义final,其余的都定义为final类型,我们知道Java中关键词final修饰的域成为最终域。用关键词final修饰的变量一旦赋值,就不能改变,也称为修饰的标识为常量。这就意味着我们删除或者增加一个节点的时候,就必须从头开始重新建立Hash链,因为next引用值需要改变。 (2)segment类 Segment 类继承于 ReentrantLock 类,从而使得 Segment 对象能充当锁的角色。每个 Segment 对象用来守护其(成员对象 table 中)包含的若干个桶。   table 是一个由 HashEntry 对象组成的数组。table 数组的每一个数组成员就是散列映射表的一个桶。   count 变量是一个计数器,它表示每个 Segment 对象管理的 table 数组(若干个 HashEntry 组成的链表)包含的 HashEntry 对象的个数

实现 Java 本地缓存,该从这几点开始

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

Need simple explanation how “lock striping” works with ConcurrentHashMap

假装没事ソ 提交于 2019-11-28 18:20:20
According to Java Concurrency in Practice, chapter 11.4.3 says: Lock splitting can sometimes be extended to partition locking on a variablesized set of independent objects, in which case it is called lock striping. For example, the implementation of ConcurrentHashMap uses an array of 16 locks, each of which guards 1/16 of the hash buckets; bucket N is guarded by lock N mod 16. I still have problems to understand and visualize the lock striping and buckets mechanism. Can someone explain this with good understanding words :) Thanks in advance. The hash map is built on an array, where the hash

如何在很短的时间内将大量数据插入到ConcurrentHashMap(转)

对着背影说爱祢 提交于 2019-11-28 18:07:41
将大批量数据保存到map中有两个地方的消耗将会是比较大的:第一个是扩容操作,第二个是锁资源的争夺。第一个扩容的问题,主要还是要通过配置合理的容量大小和扩容因子,尽可能减少扩容事件的发生;第二个锁资源的争夺,在put方法中会使用synchonized对头节点进行加锁,而锁本身也是分等级的,因此我们的主要思路就是尽可能的避免锁等级。所以,针对第二点,我们可以将数据通过通过ConcurrentHashMap的spread方法进行预处理,这样我们可以将存在hash冲突的数据放在一个组里面,每个组都使用单线程进行put操作,这样的话可以保证锁仅停留在偏向锁这个级别,不会升级,从而提升效率。 其他: ConcurrentHashMap 1.7和1.8的区别 1、整体结构 1.7:Segment + HashEntry + Unsafe 1.8: 移除Segment,使锁的粒度更小,Synchronized + CAS + Node + Unsafe 2、put() 1.7:先定位Segment,再定位桶,put全程加锁,没有获取锁的线程提前找桶的位置,并最多自旋64次获取锁,超过则挂起。 1.8:由于移除了Segment,类似HashMap,可以直接定位到桶,拿到first节点后进行判断,1、为空则CAS插入;2、为-1则说明在扩容,则跟着一起扩容;3、else则加锁put(类似1.7) 3

Java高级面试题及答案

你说的曾经没有我的故事 提交于 2019-11-28 16:20:44
List和Set比较,各自的子类比较 对比一: Arraylist与LinkedList的比较 1、ArrayList是实现了基于动态数组的数据结构,因为地址连续,一旦数据存储好了,查询操作效率会比较高(在内存里是连着放的)。 2、因为地址连续, ArrayList要移动数据,所以插入和删除操作效率比较低。 3、LinkedList基于链表的数据结构,地址是任意的,所以在开辟内存空间的时候不需要等一个连续的地址,对于新增和删除操作add和remove,LinedList比较占优势。 4、因为LinkedList要移动指针,所以查询操作性能比较低。 适用场景分析: 当需要对数据进行对此访问的情况下选用ArrayList,当需要对数据进行多次增加删除修改时采用LinkedList。 对比二: ArrayList与Vector的比较 1、Vector的方法都是同步的,是线程安全的,而ArrayList的方法不是,由于线程的同步必然要影响性能。因此,ArrayList的性能比Vector好。 2、当Vector或ArrayList中的元素超过它的初始大小时,Vector会将它的容量翻倍,而ArrayList只增加50%的大小,这样。ArrayList就有利于节约内存空间。 3、大多数情况不使用Vector,因为性能不好,但是它支持线程的同步,即某一时刻只有一个线程能够写Vector

When should I use ConcurrentSkipListMap?

北战南征 提交于 2019-11-28 15:38:08
In Java, ConcurrentHashMap is there for better multithreading solution. Then when should I use ConcurrentSkipListMap ? Is it a redundancy? Does multithreading aspects between these two are common? Kevin Montrose These two classes vary in a few ways. ConcurrentHashMap does not guarantee* the runtime of its operations as part of its contract. It also allows tuning for certain load factors (roughly, the number of threads concurrently modifying it). ConcurrentSkipListMap , on the other hand, guarantees average O(log(n)) performance on a wide variety of operations. It also does not support tuning

JUC 一 ConcurrentHashMap

99封情书 提交于 2019-11-28 13:46:44
ConcurrentHashMap 同步容器类是 Java5 增加的一个线程安全的哈希表 介于 HashMap 与 Hashtable 之间,内部采用"锁分段"机制替代Hashtable的独占锁,进而提高性能; 当期望许多线程访问一个给定collection时, ConcurrentHashMap通常优于同步的HashMap , ConcurrentSkipListMap通常优于同步的TreeMap 当期望的读数和遍历远远大于列表的更新数时, CopyOnWriteArrayList优于同步的ArrayList 来源: https://www.cnblogs.com/loveer/p/11409543.html