19.并发下的ArrayListHashMap,Integer加锁问题
Posted fly-book
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了19.并发下的ArrayListHashMap,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
//两个线程每次加锁可能都加在了不同的对象实例上
以上是关于19.并发下的ArrayListHashMap,Integer加锁问题的主要内容,如果未能解决你的问题,请参考以下文章