ArrayList线程不安全
ArrayList 线程安全问题,注意看源码
并未加锁
List线程安全解决方案
- Vector
jdk1.0已经引入,线程安全实现为synchronized
- Collections#synchronizedList,SynchronizedMap
源代码中Collections中自己内部类实现加锁机制。
如下部分代码:通过synchronized实现加锁线程安全
public boolean isEmpty() {
synchronized (mutex) {return c.isEmpty();}
}
public boolean contains(Object o) {
synchronized (mutex) {return c.contains(o);}
}
public Object[] toArray() {
synchronized (mutex) {return c.toArray();}
}
- CopyOnWriteArrayList
在修改原数组时都会进行加锁,然后对原数组进行copy,再进行修改保证线程安全
public E remove(int index) {
synchronized (lock) {
Object[] es = getArray();
int len = es.length;
E oldValue = elementAt(es, index);
int numMoved = len - index - 1;
Object[] newElements;
if (numMoved == 0)
newElements = Arrays.copyOf(es, len - 1);
else {
newElements = new Object[len - 1];
System.arraycopy(es, 0, newElements, 0, index);
System.arraycopy(es, index + 1, newElements, index,
numMoved);
}
setArray(newElements);
return oldValue;
}
}
源码分析
HashSet线程不安全
源码:未加锁
解决方案:CopyOnWriteArraySet,同理CopyOnWriteArrayList
hashMap线程不安全
HashMap?ConcurrentHashMap?相信看完这篇没人能难住你! 吐了。有复杂,要慢慢看
解决方案ConcurrentHashMap,原理上来说:ConcurrentHashMap 采用了分段锁技术,其中 Segment 继承于 ReentrantLock。不会像 HashTable 那样不管是 put 还是 get 操作都需要做同步处理,理论上 ConcurrentHashMap 支持 CurrencyLevel (Segment 数组数量)的线程并发。每当一个线程占用锁访问一个 Segment 时,不会影响到其他的 Segment。