ConcurrentHashMap的size()方法在Java 1.7和1.8中的实现有所不同,但它们的线程安全性都是有所保障的,尽管这种保障是弱一致性的。 Java 1.7:在Java 1.7中,size()方法会尝试多次(通常是两到三次)不加锁地读取各个Segment的计数器值,并比较这些值是否一致。如果一致,则认为当前读取的计数器总和是准确的,并将其返回。
真要用size的值进行操作还是得在外边加锁。 2017-12-21 回复7 fang-cai3 是的,我也觉得.多线程环境就像一个混乱的菜市场.时时刻刻都有人进出. 你无法精确统计某一个时刻的人数.同时就算精确统计也没啥意义.可能0.01s后数字又变了. 2021-03-23 回复4 讯言 小灰不来个1.8的讲解吗?
ConcurrentHashMap 是线程安全的,意味着它可以保证多个线程同时对它进行读写操作时,不会出现数据不一致...
但是这中数据结构在实现HashMap的时候并不是线程安全的,因为在HashMap扩容的时候,是会将原先的链表迁移至新的链表数组中,在迁移过程中多线程情况下会有造成链表的死循环情况(JDK1.7之前的头插法);还有就是在多线程插入的时候也会造成链表中数据的覆盖导致数据丢失。 所以就出现了线程安全的HashMap类似的hash表集合,...
开发人员误以为使用ConcurrentHashMap就不会有线程安全问题,于是不加思索地写出了下面的代码:在每一个线程的代码逻辑中先通过size方法拿到当前元素数量,计算ConcurrentHashMap目前还需要补充多少元素,并在日志中输出了这个值,然后通过putAll方法把缺少的元素添加进去。
3. size()方法效率更高,采用了中间变量进行存储,不需要遍历,但是不保证线程安全即准确数据。 1. 2. 3. 4. 5. Node(jdk1.8): static class Node<K,V> implements Map.Entry<K,V> { final int hash; final K key; volatile V val; volatile Node<K,V> next; ...
Concurrenthashmap线程安全的,1.7是在jdk1.7中采用Segment + HashEntry的方式进行实现的,lock加在Segment上面。1.7size计算是先采用不加锁的方式,连续计算元素的个数,最多计算3次: (1)如果前后两次计算结果相同,则说明计算出来的元素个数是准确的; (2)如果前后两次计算结果都不同,则给每个Segment进行加锁,再计算一...
size方法 既然每一个Segment都各自加锁,那么我们在统计size()的时候怎么保证解决一直性的问题,比如我们在计算size时,有其他线程在添加或删除元素。 /** * Returns the number of key-value mappings in this map. If the * map contains more than Integer.MAX_VALUE elements, returns ...
我们都知道,HashMap是非线程安全的容器,那么为什么ConcurrentHashMap能够做到线程安全呢? 底层结构 首先看一下ConcurrentHashMap的底层数据结构,在Java8中,其底层的实现方式与HashMap一样的,同样是数组、链表和红黑树,下面所有的讨论都是基于Java 1.8。 transientvolatileNode<K,V>[] table; ...
ConcurrentHashMap.size 因为size是map的热点区域,每个造成数量变化的操作都需要去修改它,就要保证size值的同步,这样就会影响分段锁的伸缩性。所以每段都各自维护了一个计数器, 总结: 分段锁机制下 任意数量的读取线程可以并发得访问Map,读线程和写线程可以并发执行,并且一定数据量的写入线程可以并发得修改Map。