2.8.3 并发下诡异的HashMap

package 第二章.并发下诡异的HashMap;

import org.junit.Test;

import java.util.HashMap;import java.util.Map;import java.util.concurrent.atomic.AtomicInteger;

/** * Created by zzq on 2018/1/19. */public class HashMapMultiThread {    static HashMap<String, String> map = new HashMap<String, String>();    static AtomicInteger integer=new AtomicInteger(0);    public static class AddThread extends Thread {        int start = 0;

public AddThread(int start) {            this.start = start;        }

@Override        public void run() {            for (int i = start; i < 100000; i += 2) {                 String put = map.put(Integer.toString(i), Integer.toString(i));//                System.out.println(map.size());            }        }    }    public static void main(String args[]) throws InterruptedException {        Thread thread1 = new Thread(new HashMapMultiThread.AddThread(0));        Thread thread2 = new Thread(new HashMapMultiThread.AddThread(1));        thread1.start();        thread2.start();        thread1.join();        thread2.join();        thread2.join();        thread2.join();        int a=0;        for (String i:map.keySet()){             if(!i.equals(map.get(i))){//                 System.out.println(i);                 a++;             }        }        System.out.println(map.size());        System.out.println(a);    }    @Test    public void aaa(){        System.out.println(8 & 32);    }}
1.实例中我们可以看出1.8为例:(2个线程得到的size 不一定是2个线程数量之和)

每次添加之前,会执行 int i = indexFor(hash, table.length); 获取table的下标值,而 indexFor这个方法中(下面为源码)

static int indexFor(int h, int length) {           // assert Integer.bitCount(length) == 1 : "length must be a non-zero power of 2";           return h & (length-1);       }    这个函数返回一个值, 作为table的下标  Entry<K,V>[] table = (Entry<K,V>[]) EMPTY_TABLE;

并发说明:由于在某一时刻2个线程获取的下标值相同,那么就会造成以上情况。

2.如果jdk使用1.7的情况下,那么程序会造成死锁,死锁的原因,请看下面的分析:

假如有两个线程P1、P2,以及链表 a=》b=》null1、P1先执行,执行完"Entry<K,V> next = e.next;"代码后发生阻塞,或者其他情况不再执行下去,此时e=a,next=b

2、而P2已经执行完整段代码,于是当前的新链表newTable[i]为b=》a=》null

3、P1又继续执行"Entry<K,V> next = e.next;"之后的代码,则执行完"e=next;"后,newTable[i]为a《=》b,则造成回路,while(e!=null)一直死循环

原文地址:https://www.cnblogs.com/anxbb/p/8425474.html

时间: 2024-10-12 20:08:31

2.8.3 并发下诡异的HashMap的相关文章

并发下诡异的HashMap

最近研读<Java高并发程序设计>葛一鸣.郭超编著,读到2.8.3时,题目便是并发下诡异的HashMap,摘抄如下: -----------摘抄开始-------------- HashMap同样不是线程安全的.当你使用多线程访问HashMap时,也可能会遇到意想不到的错误.不过和ArrayList不同,HashMap的问题似乎更加诡异. package cn.baokx; import java.util.HashMap; import java.util.Map; public class

2 java并行基础

我们认真研究如何才能构建一个正确.健壮并且高效的并行系统. 进程与线程 进程(Process):是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础. 进程是线程的容器.程序是指令.数据和其组织形式的描述,进程是程序的实体.进程中可以容纳若干个线程. 进程和线程的关系:线程就是轻量级的进程,是程序执行的最小单位.为什么我们使用多线程而不是多进程?因为线程间的切换调度成本远远小于进程,所以我们使用多线程而不是多进程. 线程的生命周期 线程的所有状

HhashMap HashTable ConcurrentHashMap

hashMap hashTable concurrentHashMap hashMap的效率高于hashTable,hashMap是线程不安全的,并发时hashMap put方法容易引起死循环,导致cpu利用率达到100% 所以高并发下不能使用hashMap,而是用ConcurentHashMap,则不会出现这种情况

19.并发下的ArrayList、HashMap,Integer加锁问题

import java.util.ArrayList; import java.util.Vector; /** * 并发下的ArrayList */ public class ArrayListMultiThread { static ArrayList<Integer> arrayList = new ArrayList<>(); // static Vector<Integer> arrayList = new Vector<>(); //解决方式 使

HashMap在高并发下引起的死循环

HashMap其实并不是线程安全的,在高并发的情况下,是很可能发生死循环的,由此造成CPU 100%,这是很可怕的,所以在多线程的情况下,用HashMap是很不妥当的行为,应采用线程安全类ConcurrentHashMap进行代替. HashMap死循环原因 HashMap进行存储时,如果size超过当前最大容量*负载因子时候会发生resize,首先看一下resize原代码 void resize(int newCapacity) { Entry[] oldTable = table; int

HashMap在高并发下如果没有处理线程安全会有怎样的安全隐患,具体表现是什么

Hashmap在并发环境下,可能出现的问题: 1.多线程put时可能会导致get无限循环,具体表现为CPU使用率100%: 原因:在向HashMap put元素时,会检查HashMap的容量是否足够,如果不足,则会新建一个比原来容量大两倍的Hash表,然后把数组从老的Hash表中迁移到新的Hash表中,迁移的过程就是一个rehash()的过程,多个线程同时操作就有可能会形成循环链表,所以在使用get()时,就会出现Infinite Loop的情况 // tranfer()片段 // 这是在res

漫画:高并发下的HashMap

这一期我们来讲解高并发环境下,HashMap可能出现的致命问题. HashMap的容量是有限的.当经过多次元素插入,使得HashMap达到一定饱和度时,Key映射位置发生冲突的几率会逐渐提高. 这时候,HashMap需要扩展它的长度,也就是进行Resize. 影响发生Resize的因素有两个:   1.Capacity HashMap的当前长度.上一期曾经说过,HashMap的长度是2的幂. 2.LoadFactor HashMap负载因子,默认值为0.75f. 衡量HashMap是否进行Res

高并发下,HashMap会产生哪些问题?

HashMap在高并发环境下会产生的问题 HashMap其实并不是线程安全的,在高并发的情况下,会产生并发引起的问题: 比如: HashMap死循环,造成CPU100%负载 触发fail-fast 下面逐个分析下出现上述情况的原因: HashMap死循环的原因 HashMap进行存储时,如果size超过(当前最大容量*负载因子)时候会发生resize,首先看一下resize源代码: void resize(int newCapacity) { Entry[] oldTable = table;

HashMap并发下死循环问题解析

首先小伙伴要明确:死循环问题在JDK 1.8 之前是存在的,JDK 1.8 通过增加loHead和loTail进行了修复. 在JDK 1.7及之前 HashMap在并发情况下导致循环问题,致使服务器cpu飙升至100%,那么今天就来解析一下线程不安全的HashMap在高并发的情况下是如何造成死循环的. 要探究hashmap死循环的原因 首先要知道hashmap的源码 这样才能从根本上对hashmap进行理解 . 首先hashmap进行元素的插入,在元素个数达到阀值时: 首先小伙伴要明确:死循环问