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
            //两个线程每次加锁可能都加在了不同的对象实例上
        }
    }
    
  • 相关阅读:
    14.4.9 Configuring Spin Lock Polling 配置Spin lock 轮询:
    14.4.8 Configuring the InnoDB Master Thread IO Rate 配置InnoDB Master Thread I/O Rate
    14.4.7 Configuring the Number of Background InnoDB IO Threads 配置 后台InnoDB IO Threads的数量
    14.4.7 Configuring the Number of Background InnoDB IO Threads 配置 后台InnoDB IO Threads的数量
    14.4.6 Configuring Thread Concurrency for InnoDB 配置Thread 并发
    14.4.6 Configuring Thread Concurrency for InnoDB 配置Thread 并发
    14.4.5 Configuring InnoDB Change Buffering 配置InnoDB Change Buffering
    14.4.5 Configuring InnoDB Change Buffering 配置InnoDB Change Buffering
    14.4.4 Configuring the Memory Allocator for InnoDB InnoDB 配置内存分配器
    14.4.4 Configuring the Memory Allocator for InnoDB InnoDB 配置内存分配器
  • 原文地址:https://www.cnblogs.com/fly-book/p/11387390.html
Copyright © 2011-2022 走看看