就需要用到线程安全的容器。 使用了线程安全的并发工具,并不代表解决了所有线程安全问题。 ThreadLocalRandom 可将其实例设置到静态变量,在多线程下重用吗?...我们都知道ConcurrentHashMap是个线程安全的哈希表容器,但它仅保证提供的原子性读写操作线程安全。...开发人员误以为使用ConcurrentHashMap就不会有线程安全问题,于是不加思索地写出了下面的代码:在每一个线程的代码逻辑中先通过size方法拿到当前元素数量,计算ConcurrentHashMap...你往这个篮子装100个桔子的操作不是原子性的,在别人看来可能会有一个瞬间篮子里有964个桔子,还需要补36个桔子。...如果需要确保需要手动加锁 诸如size、isEmpty和containsValue等聚合方法,在并发下可能会反映ConcurrentHashMap的中间状态。
计算key的哈希值for自旋保证put成功如果没有初始化就初始化table有可能多个线程去调用initTable()方法去初始化,用cas加锁就行了,成功一次就行了通过与哈希取模计算数组下标,如果下标节点为...put进去之后,会对链表长度进行判断,如果链表的长度大于等于8,进行扩容或者转化为红黑树链表的扩容如果tab的长度小于64,则调用tryPresize()方法进行扩容链表的扩容的本质是16->32,将数组扩容一倍...,然后将老数组的数据迁移到新的数组如果为空就初始化数组,跟之前的initTable()方法一样如果已经是最大容量了,直接返回判断sizeCtl是否小于0,因为只有在扩容中的时候sizeCtl才会小于0变成...-1,多线程扩容,高16位表示当前的扩容标记,保证唯一性,低16位表示当前扩容的线程数量,每增加一个扩容线程,就会在低16位+1实现数据转移 transfer()计算每个线程处理数据的区间大小,默认最小是...ConcurrentHashMap里面也有死循环,作者留下的“彩蛋”了解一下? - 掘金这道面试题我真不知道面试官想要的回答是什么
前言 之前在面试的过程中有被问到,ConcurrentHashMap的size方法是线程安全的吗? 这个问题,确实没有答好。这次来根据源码来了解一下,具体是怎么一个实现过程。...但是这中数据结构在实现HashMap的时候并不是线程安全的,因为在HashMap扩容的时候,是会将原先的链表迁移至新的链表数组中,在迁移过程中多线程情况下会有造成链表的死循环情况(JDK1.7之前的头插法...Hashtable实现线程安全的代价比较大,那就是在所有可能产生竞争方法里都加上了synchronized,这样就会导致,当出现竞争的时候只有一个线程能对整个Hashtable进行操作,其他所有线程都需要阻塞等待当前获取到锁的线程执行完成...JDK1.8中的ConcurrentHashMap在执行put()方法的时候还是有些复杂的,主要是为了保证线程安全才做了一系列的措施。 源码如下: ? 第一步通过key进行hash。...总结 无论是JDK1.7还是JDK1.8中,ConcurrentHashMap的size()方法都是线程安全的,都是准确的计算出实际的数量,但是这个数据在并发场景下是随时都在变的。
使用了线程安全的并发工具,并不代表解决了所有线程安全问题。 ThreadLocalRandom 可将其实例设置到静态变量,在多线程下重用吗?...我们都知道ConcurrentHashMap是个线程安全的哈希表容器,但它仅保证提供的原子性读写操作线程安全。...开发人员误以为使用ConcurrentHashMap就不会有线程安全问题,于是不加思索地写出了下面的代码:在每一个线程的代码逻辑中先通过size方法拿到当前元素数量,计算ConcurrentHashMap...你往这个篮子装100个桔子的操作不是原子性的,在别人看来可能会有一个瞬间篮子里有964个桔子,还需要补36个桔子。...如果需要确保需要手动加锁 诸如size、isEmpty和containsValue等聚合方法,在并发下可能会反映ConcurrentHashMap的中间状态。
ConcurrentHashMap是如何实现线程安全的 文章目录 ConcurrentHashMap是如何实现线程安全的 前言 相关概念 Amdahl定律 初始化数据结构时的线程安全 总结...put操作的线程安全 总结 扩容操作的线程安全 扩容时的get操作 多线程协助扩容 在什么情况下会进行扩容操作?...get方法如何线程安全地获取key、value? put方法如何线程安全地设置key、value? size方法如果线程安全地获取容器容量? 底层数据结构扩容时如果保证线程安全?...同时直接锁住头节点,保证了线程安全 Unsafe的getObjectVolatile方法:此方法确保获取到的值为最新 扩容操作的线程安全 在扩容时,ConcurrentHashMap支持多线程并发扩容,...统计容器大小的线程安全 ConcurrentHashMap在每次put操作之后都会调用addCount方法,此方法用于统计容器大小且检测容器大小是否达到阈值,若达到阈值需要进行扩容操作,这在上面也是有提到的
而这些问题,只要使用 ConcurrentHashMap 就可以完美解决了,那问题来了,ConcurrentHashMap 是如何保证线程安全的?它的底层又是如何实现的?接下来我们一起来看。...: JDK 1.7 线程安全实现 了解了 ConcurrentHashMap 的底层实现,再看它的线程安全实现就比较简单了。...接下来,我们通过添加元素 put 方法,来看 JDK 1.7 中 ConcurrentHashMap 是如何保证线程安全的,具体实现源码如下: final V put(K key, int hash,...,这样就能保证多个线程同时访问 ConcurrentHashMap 时,同一时间只有一个线程能操作相应的节点,这样就保证了 ConcurrentHashMap 的线程安全了。...JDK 1.8 线程安全实现 在 JDK 1.8 中 ConcurrentHashMap 使用的是 CAS + volatile 或 synchronized 的方式来保证线程安全的,它的核心实现源码如下
而这些问题,只要使用ConcurrentHashMap就可以完美地解决。那问题来到了,ConcurrentHashMap它是如何保证线程安全的呢?...了解了ConcurrentHashMap的基本结构设计,我们再来看它的线程安全实现,就比较简单了。 接下来我们来对照JDK1.7中ConcurrentHashMap的put()方法源码实现。...ConcurrentHashMap的线程安全。...也就是说ConcurrentHashMap的线程安全是建立在Segment加锁的基础上的,所以,我们称它为分段锁或者片段锁,如图中所示。 那JDK1.8又是如何实现的呢?...这样就能保证并发访问时的线程安全了。 如果把上面的执行用一句话归纳的话,就相当于是ConcurrentHashMap通过对头结点加锁来保证线程安全的。
从JDK1.2起,就有了HashMap,正如前一篇文章所说,HashMap不是线程安全的,因此多线程操作时需要格外小心。...ConcurrentHashMap具体是怎么实现线程安全的呢,肯定不可能是每个方法加synchronized,那样就变成了HashTable。...(1)Thread1和Thread2先后进入Segment.put方法时,Thread1会首先获取到锁,可以进入,而Thread2则会阻塞在锁上: ?...(2)切换到Thread3,也走到Segment.put方法,因为7所存储的Segment和3、4不同,因此,不会阻塞在lock(): ?...以上就是ConcurrentHashMap的工作机制,通过把整个Map分为N个Segment(类似HashTable),可以提供相同的线程安全,但是效率提升N倍,默认提升16倍。
或者使用写时复制的CopyOnWriteArrayList,性能更佳呀!技术言论虽然自由,但面对魔鬼面试官时,我们更在乎的是这些真的正确吗? 2 ConcurrentHashMap真的安全吗?...我们都知道ConcurrentHashMap是个线程安全的哈希表容器,但它仅保证提供的原子性读写操作线程安全。...开发人员误以为使用ConcurrentHashMap就不会有线程安全问题,于是不加思索地写出了下面的代码:在每一个线程的代码逻辑中先通过size方法拿到当前元素数量,计算ConcurrentHashMap...你往这个篮子装100个桔子的操作不是原子性的,在别人看来可能会有一个瞬间篮子里有964个桔子,还需要补36个桔子。...如果需要确保需要手动加锁 诸如size、isEmpty和containsValue等聚合方法,在并发下可能会反映ConcurrentHashMap的中间状态。
如何保证容器是线程安全的?ConcurrentHashMap 如何高效的线程安全? Java提供了不同层面的线程安全支持。...如何保证线程安全 首先要保障线程安全的几个基本特性, 原子性,可见性,有序性。其次可以通过封装的方式将内部对象保护起来,保证变量对象的不可变性,一般就线程安全了。...理解基本的线程安全工具 理解传统集合矿建并发变成中 Map 存在的问题,清楚简单同步方式的不足 梳理并发包内,尤其是 ConcurrentHashMap 采取了哪些方法来提高并发表现。...最好能够掌握 ConcurrentHashMap 自身的演进,目前很多分析资料还是基于早期版本。 为什么需要 ConcurrentHashMap Hashtable 是怎样实现线程安全的。...Hashtable 能够保证线程安全,但是它的基本就是将 put ,get ,size 等各种操作加上 synchronized, 这样就导致了所有并发操作都要竞争一把锁,一个线程在进行同步操作时,其他线程只能等待
Java 提供了不同层面的线程安全支持。...更加普遍的选择是利用并发包提供的线程安全容器类, 它提供了: 各种并发容器,比如 ConcurrentHashMap、CopyOnWriteArrayList。...各种线程安全队列(Queue/Deque),如 ArrayBlockingQueue、SynchronousQueue。 各种有序容器的线程安全版本等。...具体保证线程安全的方式,包括有从简单的 synchronize 方式,到基于更加精细化的,比如基于分离锁实现的 ConcurrentHashMap 等并发实现等。...Hashtable 本身比较低效,因为它的实现基本就是将 put、get、size 等各种方法加 上“synchronized”。
先前介绍了 Java 集合框架 的典型容器类,它们绝大部分都不是线程安全的,仅有的线程安全实现,比如 Vector、Stack,在性能方面也远不尽如人意。...ConcurrentHashMap 如何实现高效地线程安全? 典型回答 Java 提供了不同层面的线程安全支持。...为什么需要 ConcurrentHashMap? Hashtable 本身比较低效,因为它的实现基本就是将 put、get、size 等各种方法加上“synchronized”。...我们都知道HashMap 不是线程安全的,并发情况会导致类似 CPU 占用 100% 等一些问题,那么能不能利用 Collections 提供的同步包装器来解决问题呢?...Segment,然后进行线程安全的 put 操作: public V put(K key, V value) { Segment s; if (value == null
我在之前两讲介绍了Java集合框架的典型容器类,它们绝大部分都不是线程安全的,仅有的线程安全实现,比如Vector、Stack,在性能方面也远不尽如人意。...今天我要问你的问题是,如何保证容器是线程安全的?ConcurrentHashMap如何实现高效地线程安全?典型回答Java提供了不同层面的线程安全支持。...前面已经提过HashMap不是线程安全的,并发情况会导致类似CPU占用100%等一些问题,那么能不能利用Collections提供的同步包装器来解决问题呢?...private satic class SynchronizedMap 如何保证集合是线程安全的? ConcurrentHashMap如何实现高效地线程安全?...= null) { //省略 } return null; }而对于put操作,首先是通过二次哈希避免哈希冲突,然后以Unsafe调用方式,直接获取相应的Segment,然后进行线程安全的put操作:
来自:www.cnblogs.com/keeya/p/9632958.html 我们知道,ConcurrentHashmap(1.8)这个并发集合框架是线程安全的,当你看到源码的get操作时,会发现get...//eh=-2,说明该节点是一个TreeBin,此时调用TreeBin的find方法遍历红黑树,由于红黑树有可能正在旋转变色,所以find里会有读写锁。...是如何保证读到的数据不是脏数据的呢?...普通的共享变量不能保证可见性,因为普通共享变量被修改之后,什么时候被写入主存是不确定的,当其他线程去读取时,此时内存中可能还是原来的旧值,因此无法保证可见性。...其实就是为了使得Node数组在扩容的时候对其他线程具有可见性而加的volatile 总结 在1.8中ConcurrentHashMap的get操作全程不需要加锁,这也是它比其他并发集合比如hashtable
我:StringBuilder不是线程安全的,StringBuffer是线程安全的 面试官:那StringBuilder不安全的点在哪儿? 我:。。。...(哑巴了) 在这之前我只记住了StringBuilder不是线程安全的,StringBuffer是线程安全的这个结论,至于StringBuilder为什么不安全从来没有去想过。...假设这个时候count值为10,len值为1,两个线程同时执行到了第七行,拿到的count值都是10,执行完加法运算后将结果赋值给count,所以两个线程执行完后count值为11,而不是12。...这个时候线程1的cpu时间片用完了,线程2继续执行。线程2执行完整个append()方法后count变成6了。...那么StringBuffer用什么手段保证线程安全的?这个问题你点进StringBuffer的append()方法里面就知道了。 - END -
近期在vpp-dev订阅邮箱中有一个关于bihash的在查询过程中返回的value数值为-1,导致在后续使用中产生崩溃。所以认为bihash并不是线程安全的。下面就一起来看一下邮件的内容。...为此详细研究了bihash并提出了自己的解决方案: bihash线程不安全的原因 bihash表中的桶数永远不会改变。每个桶都有一个锁位。...没有什么可以阻止更新程序更改读者当前正在查看的数据,甚至可以立即删除hash数据。此处是否可以正确工作的判定方法是我们是否可以对查找和更新操作的相对性能进行假设。...请注意,检查键和获取值不是原子的,因此如果我们在中间被抢占,结果可能是假的。...关于 isolcpus,目前这是作为优化而不是先决条件提出的。如果没有 isolcpus,线程可能会被抢占任意长的时间。这意味着无论我们为版本字段分配多少位,有时它们都不够。
我:StringBuilder不是线程安全的,StringBuffer是线程安全的 面试官:那StringBuilder不安全的点在哪儿? 我:。。。...(哑巴了) 在这之前我只记住了StringBuilder不是线程安全的,StringBuffer是线程安全的这个结论,至于StringBuilder为什么不安全从来没有去想过。...假设这个时候count值为10,len值为1,两个线程同时执行到了第七行,拿到的count值都是10,执行完加法运算后将结果赋值给count,所以两个线程执行完后count值为11,而不是12。...这个时候线程1的cpu时间片用完了,线程2继续执行。线程2执行完整个append()方法后count变成6了。 ?...那么StringBuffer用什么手段保证线程安全的?这个问题你点进StringBuffer的append()方法里面就知道了。
我:StringBuilder 不是线程安全的,StringBuffer 是线程安全的 面试官:那 StringBuilder 不安全的点在哪儿? 我:。。。...(哑巴了) ❞ 在这之前我只记住了 StringBuilder 不是线程安全的,StringBuffer 是线程安全的这个结论,至于 StringBuilder 为什么不安全从来没有去想过。...StringBuilder线程安全 我们看到输出了“9326”,小于预期的 10000,并且还抛出了一个 ArrayIndexOutOfBoundsException 异常(异常不是必现)。...那么 StringBuffer 用什么手段保证线程安全的?这个问题你点进 StringBuffer 的 append()方法里面就知道了。 当然是输出 10000 啦!...那么 StringBuffer 用什么手段保证线程安全的?这个问题你点进 StringBuffer 的 append()方法里面就知道了。
我:StringBuilder不是线程安全的,StringBuffer是线程安全的 面试官:那StringBuilder不安全的点在哪儿?我:。。。...(哑巴了) 在这之前我只记住了StringBuilder不是线程安全的,StringBuffer是线程安全的这个结论,至于StringBuilder为什么不安全从来没有去想过。...假设现在有两个线程同时执行了StringBuilder的append()方法,两个线程都执行完了第五行的ensureCapacityInternal()方法,此刻count=5。 ?...这个时候线程1的cpu时间片用完了,线程2继续执行。线程2执行完整个append()方法后count变成6了 ?...那么StringBuffer用什么手段保证线程安全的?这个问题你点进StringBuffer的append()方法里面就知道了。 END
大家好,又见面了,我是你们的朋友全栈君。 Java中平时用的最多的map就是hashmap但是它却是线程不安全的。 那除了hashmap还有哪些常见的线程安全的map?...1.hashtable Map hashtable=new Hashtable(); 这是所有人最先想到的,那为什么它是线程安全的?...那就看看它的源码,我们可以看出我们常用的put,get,containsKey等方法都是同步的,所以它是线程安全的 public synchronized boolean containsKey(Object...Map concurrentHashMap=new ConcurrentHashMap(); 这个是目前使用最多,而且也是最推荐的一个集合...我们看源码其实是可以发现里面的线程安全是通过cas+synchronized+volatile来实现的,其中也可看出它的锁是分段锁,所以它的性能相对来说是比较好的。整体实现还是比较复杂的。
领取专属 10元无门槛券
手把手带您无忧上云