zoukankan      html  css  js  c++  java
  • 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
            //两个线程每次加锁可能都加在了不同的对象实例上
        }
    }
    
  • 相关阅读:
    Django restfull规范
    Python3中的zip()
    关于负数的isdigit()判断
    Win7 x64安装Paramiko
    深度学习性能提高
    神经网络激励函数
    机器学习十大算法
    深度学习十大框架比较
    python 换行
    python sort() sorted() 与argsort()函数的区别
  • 原文地址:https://www.cnblogs.com/fly-book/p/11387390.html
Copyright © 2011-2022 走看看