zoukankan      html  css  js  c++  java
  • 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不总是读出值来(但这也能避免值被修改),总之各有各的好吧。

  • 相关阅读:
    Android Activity生命周期
    Android 横屏切换竖屏Activity的生命周期(转)
    (引用)mysql总结(二)
    (转载)mysql指令总结
    (引用)性能测试没有告诉你的
    参数化(引用)
    (引用)什么时候开展性能(二)
    (引用)什么时候开展性能(一)
    性能测试中容易混淆的概念
    浏览器内核
  • 原文地址:https://www.cnblogs.com/alipayhutu/p/2459365.html
Copyright © 2011-2022 走看看