ConcurrentHashMap & CopyOnWriteArrayList &

ConcurrentHashMap vs. HashMap/SynchronizedMap/HashTable

    • 什么时候用ConcurrentHashMap(),读写并发。较HashMap好在其并发性上,读不锁,写的时候锁粒度减小为segment而不是整张表,也就意味着一定程度上可以进行“并发写”。貌似自从有了Concurrent,hashMap就不得宠了。。
    • ConcurrentHashMap,不要轻易用.size(),因为它会锁整张表;
    • ConcurrentHashMap,不要轻易用.remove(),因为它会涉及到hashTable中该entry之前的所有元素都要进行拷贝操作(为什么要拷贝呢?因为entry除了value字段是变量外,其他都是final的,这样索引的时候不用同步,性能更快)。

http://xuganggogo.iteye.com/blog/321630

http://www.ibm.com/developerworks/cn/java/j-jtp07233/

http://www.ibm.com/developerworks/cn/java/java-lo-concurrenthashmap/index.html?ca=drs-

CopyOnWriteArrayList vs. ArrayList

  • 读多,写少,用CopyOnWriteArrayList效率高。为什么呢?如果是普通的ArrayList,那么在写、多线程并发访问的时候,需要锁定整个list,然后挨个写。这是神马效率?
  • CopyOnWriteArrayList,实现读写分离。读的时候不加锁不阻塞(iterator自诞生之时起就指着一个原版读,由于写是在副本上写,所以读不会出问题),写的时候可以在副本上写,写完了后指针原子再指向你,按你生效。
  • 两个问题:

(1)这个所谓“副本”就牵扯到Arrays.copyof()整个数组复制的问题,且使用到了ReentrantLock(重入锁)同步,注定影响效率,所以写多的话不适合用CopyOnWriteArrayList。

(2)如何防止并发写?大家都自顾自拿着副本写去了,这可如何是好?必须不能够啊!CopyOnWriteArray当有一个人准备搞副本之前,就加锁,直到他改完释放锁,别人才可以接着它拉副本出来搞。换句话说,set(), add(), remove()操作都是synchronized(),且内部搞副本copyIn()这个操作也是synchronized的。

http://www.cnblogs.com/sunwei2012/archive/2010/10/08/1845656.html

http://blog.csdn.net/tsyj810883979/article/details/6891540

  • 给个案例
String[] strs = {"111","222","333"};
List<String> list1 = new CopyOnWriteArrayList<String>(Arrays.asList(strs));
List<String> list2 = new ArrayList<String>();
Iterator<String> itor1 = list1.iterator(); //写前建迭代器
Iterator<String> itor2 = list2.iterator(); //写前建迭代器
list1.add("New");
list2.add("New");
 
try {
  printAll(itor1); //迭代无误,输入111,222,333
} catch (ConcurrentModificationException e) {
  System.err.println("Shouldn't get here");
}
try {
  printAll(itor2); //迭代过程中在itor.next()处抛出异常
} catch (ConcurrentModificationException e) {
  System.err.println("Will get here.");
}
 
private static void printAll(Iterator<String> itor) {
while (itor.hasNext()) {
  System.out.println(itor.next());
}

现象解释:写前建迭代器,itor1看到的是111,222,333,而itor2看到的是空,在list1(copyonwrite)修改后,不影响itor1的读过程,照样能把111,222,333读出来,而list2(arraylist)则因为发现expectedCount与modeCount值不匹配而抛出异常。读也是有讲究的,itor1可以总是读出值来(虽然不是最新的),itor2不总是读出值来(但这也能避免值被修改),总之各有各的好吧。

原文地址:https://www.cnblogs.com/alipayhutu/p/2459365.html