ConcurrentHashMap
- 在Java7之前,底层数据结构采用分段数组+链表。采用分段锁实现线程安全。
分段锁:每把锁只锁容器内的一部分数据,多线程访问不同的数据段时,就不存在锁竞争,提高并发访问效率。
- 在Java8时,底层和HashMap一样,采用数组+链表/红黑树。采用Syn+CAS实现线程安全。
Syn在1.6做过很多优化。
CAS:Compare And Swap。只有当预期值和当前值一样时,才允许修改当前值。
相对于锁,CAS不会阻塞,不涉及到上下文切换的问题。
如下图中AtomicInteger的compreAndSet:
HashTable是锁住整个hash表,效率非常低下,并且复合操作时并不是线程安全的。
复合操作:
“若存在则删除” “若不存在则添加”。
CopyOnWriteArrayList、CopyOnWriteArraySet
CopyOnWriteArrayList:写入时复制。
用法举例:
private static List<String> list = Collections.synchronizedList(new ArrayList<String>());
static {
// list添加一些元素
}
@Override
public void run() {
Iterator<String> it = list.iterator();
while (it.hasNext()){
System.out.println(it.next());
list.add("something");
}
}
此时将会报:ConcurrentModificationException
private static List<String> list = new CopyOnWriteArrayList<String>();//Collections.synchronizedList(new ArrayList<String>());
static {
// list添加一些元素
}
@Override
public void run() {
Iterator<String> it = list.iterator();
while (it.hasNext()){
System.out.println(it.next());
list.add("something");
}
}
此时可以正常运行。
由于每次写入时都复制,所以效率很低。当添加操作多时,不适合使用CopyOnWriteArrayList。适合并发迭代。