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<>(); //解决方式 使用线程安全的Vector代替ArrayList
    public static class AddThread implements Runnable{
        @Override
        public void run() {
//            synchronized (ArrayListMultiThread.class){  //解决方式加锁
                for (int i = 0; i < 1000000; i++) {
                    arrayList.add(i);
                }
//            }
        }
    }
    public static void main(String[] args) throws InterruptedException{
        Thread thread1 = new Thread(new AddThread());
        Thread thread2 = new Thread(new AddThread());
        thread1.start();
        thread2.start();
        thread1.join();thread2.join();
        System.out.println(arrayList.size());
        //Exception in thread "Thread-1" java.lang.ArrayIndexOutOfBoundsException: 10
        //  at java.util.ArrayList.add(ArrayList.java:463)
        //  at com.combat.ArrayListMultiThread$AddThread.run(ArrayListMultiThread.java:11)
        //  at java.lang.Thread.run(Thread.java:748)
        //1000001

        //这种结果是因为ArrayList在扩容过程中,内部一致性被破坏,但由于没有锁的保护,另一个线程访问到了不一致的内部状态
        //导致出现越界问题

        //结果二:2000000
        //结果二:小于2000000
    }
}
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 并发下的HashMap
 * jdk8
 */
public class HashMapMultiThread {
    static Map<String,String> map = new HashMap<>();
//    static ConcurrentHashMap<String,String> map = new ConcurrentHashMap<>(); //解决方式 用ConcurrentHashMap代替HashMap
    public static class AddThread implements Runnable{
        int start = 0;
        public AddThread(int start){
            this.start = start;
        }
        @Override
        public void run() {
//            synchronized (HashMapMultiThread.class){ // 解决方式
                for (int i = start; i < 100000; i+=2) {
                    map.put(Integer.toString(i),Integer.toBinaryString(i));
                }
//            }
        }
    }
    public static void main(String[] args) throws InterruptedException{
        Thread thread1 = new Thread(new AddThread(0));
        Thread thread2 = new Thread(new AddThread(1));
        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();
        System.out.println(map.size());
        //Exception in thread "Thread-1" Exception in thread "Thread-0" java.lang.ClassCastException: java.util.HashMap$Node cannot be cast to java.util.HashMap$TreeNode
        //  at java.util.HashMap$TreeNode.moveRootToFront(HashMap.java:1832)
        //  at java.util.HashMap$TreeNode.treeify(HashMap.java:1949)
        //  at java.util.HashMap.treeifyBin(HashMap.java:772)
        //  at java.util.HashMap.putVal(HashMap.java:644)
        //  at java.util.HashMap.put(HashMap.java:612)
        //  at com.combat.HashMapMultiThread$AddThread.run(HashMapMultiThread.java:19)
        //  at java.lang.Thread.run(Thread.java:748)
        //java.lang.ClassCastException: java.util.HashMap$Node cannot be cast to java.util.HashMap$TreeNode
        //  at java.util.HashMap$TreeNode.moveRootToFront(HashMap.java:1832)
        //  at java.util.HashMap$TreeNode.putTreeVal(HashMap.java:2012)
        //  at java.util.HashMap.putVal(HashMap.java:638)
        //  at java.util.HashMap.put(HashMap.java:612)
        //  at com.combat.HashMapMultiThread$AddThread.run(HashMapMultiThread.java:19)
        //  at java.lang.Thread.run(Thread.java:748)
        //2778

        // 结果二:小于100000

        //JDk7会出现死循环  HashMap put()是一个迭代遍历,如同遍历链表一样,但由于多线程,链表成环了,形成死循环
    }
}
/**
 * Integer加锁
 */
public class BadLockOnInteger implements Runnable{
    public static Integer i = 0;
    static BadLockOnInteger instance = new BadLockOnInteger();

    @Override
    public void run() {
        for (int j = 0; j < 10000000; j++) {
            synchronized (i){
//            synchronized (instance){ // 修改方式
                i++; //相当于 i = Integer.valueOf(i.intValue()+1);
            }
        }
    }
    public static void main(String[] args) throws InterruptedException{
        Thread thread1 = new Thread(instance);
        Thread thread2 = new Thread(instance);
        thread1.start();thread2.start();
        thread1.join();thread2.join();
        System.out.println(i);
        //12968375 小于20000000
        //java中Integer属于不变对象,一旦创建就不可能被修改
        //i++的本质是创建一个新的Integer对象,并将他的引用赋值给i
        //两个线程每次加锁可能都加在了不同的对象实例上
    }
}

原文地址:https://www.cnblogs.com/fly-book/p/11387390.html

时间: 2024-11-15 06:26:46

19.并发下的ArrayList、HashMap,Integer加锁问题的相关文章

并发下诡异的HashMap

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

2.8.2 并发下的ArrayList,以及源码分析

package 第二章.并发下的ArrayList; import java.util.ArrayList;import java.util.List; /** * Created by zzq on 2018/1/19. */public class 并发下的ArrayList { static ArrayList<Integer> list=new ArrayList<Integer>(); public static class AddThread extends Threa

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> m

Java基础知识强化之集合框架笔记55:Map集合之HashMap集合(HashMap&lt;Integer,String&gt;)的案例

1. HashMap集合(键是Integer,值是String的案例) 2. 代码示例: 1 package cn.itcast_02; 2 3 import java.util.HashMap; 4 import java.util.Set; 5 6 /* 7 * HashMap<Integer,String> 8 * 键:Integer 9 * 值:String 10 */ 11 public class HashMapDemo2 { 12 public static void main(

性能优化:使用SparseArray代替HashMap&lt;Integer,Object&gt;(转)

HashMap是java里比较常用的一个集合类,我比较习惯用来缓存一些处理后的结果.最近在做一个Android项目,在代码中定义这样一个变量,实例化时,Eclipse却给出了一个 performance 警告. 意思就是说用SparseArray<E>来替代,以获取更好性能.老实说,对SparseArray并不熟悉,第一感觉应该是Android提供的一个类.按住Ctrl点击进入SparseArray的源码,果不其然,确定是Android提供的一个工具类. 单纯从字面上来理解,SparseArr

性能优化:使用SparseArray代替HashMap&lt;Integer,Object&gt;

HashMap是java里比较常用的一个集合类,我比较习惯用来缓存一些处理后的结果.最近在做一个Android项目,在代码中定义这样一个变量,实例化时,Eclipse却给出了一个 performance 警告. 意思就是说用SparseArray<E>来替代,以获取更好性能.老实说,对SparseArray并不熟悉,第一感觉应该是Android提供的一个类.按住Ctrl点击进入SparseArray的源码,果不其然,确定是Android提供的一个工具类. 单纯从字面上来理解,SparseArr

JavaSE8基础 HashMap&lt;Integer,String&gt; keySet遍历 根据键找值

os :windows7 x64    jdk:jdk-8u131-windows-x64    ide:Eclipse Oxygen Release (4.7.0) code: package jizuiku0; import java.util.HashMap; import java.util.Set; /* * @version V17.09 */ public class MapDemo_1110 { public static void main(String[] args) { H

JavaSE8基础 HashMap&lt;Integer,String&gt; keySet values 获取所有键 所有值的集合

os :windows7 x64    jdk:jdk-8u131-windows-x64    ide:Eclipse Oxygen Release (4.7.0) code: package jizuiku0; import java.util.Collection; import java.util.HashMap; import java.util.Set; /* * @version V17.09 */ public class MapDemo_110 { public static

JavaSE8基础 HashMap&lt;Integer,String&gt; containsKey/Value 判断集合是否包含指定的键或值

os :windows7 x64    jdk:jdk-8u131-windows-x64    ide:Eclipse Oxygen Release (4.7.0) code: package jizuiku0; import java.util.HashMap; /* * @version V17.09 */ public class MapDemo_100 { public static void main(String[] args) { HashMap<Integer, String>