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
        //两个线程每次加锁可能都加在了不同的对象实例上
    }
}
posted @ 2019-08-21 10:48  fly_bk  阅读(667)  评论(0编辑  收藏  举报