`
cloudeagle_bupt
  • 浏览: 538989 次
文章分类
社区版块
存档分类
最新评论

ConcurrencyHashMap并发修改性能比较

阅读更多

由于ConcurrecyHashMap允许并发修改,无需加锁,因此测试其性能


package concurrencyTest;

import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;



public class ConcurrencyReadTest {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		ConcurrentHashMap<Integer, Integer>  map = new ConcurrentHashMap<Integer, Integer>() ;
		for(int i=0;i<100000 ; i++)
			map.put(i, i+111111) ;
		
		long start = System.currentTimeMillis() ;
		Thread t1 = new Thread(new Worker(map)) ;
		Thread t2 = new Thread(new Worker(map)) ;
		
		t1.start(); 
		t2.start();
		
		try {
			t1.join() ;
			t2.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("Read last : " + (System.currentTimeMillis() - start) + " ms");
	}
}

class Worker implements Runnable {
	ConcurrentHashMap<Integer, Integer>  sharemap ;
    int num = 0 ;
	
	public Worker(ConcurrentHashMap<Integer, Integer> map) {
		sharemap = map ;
	}
	
	@Override
	public void run() {
		 it = sharemap.values().iterator();
		 Integer i = poll(); 
		 while(i!=null) {
			 i = poll() ;
			 num++ ;
		 }
		 System.out.println("poll " + num + " elements!");
	}
	

	Iterator<Integer> it;

	public Integer poll() {
		     if (sharemap.size() > 0 && it!=null && it.hasNext()) {
		         Integer m = it.next();
		         it.remove();
		         return m;
		       } else {
		         return null;
		       }
	}
}

100000数据

并发读取
47
62
56


单独读取
31
47
47


1000000数据
281
297
281


单独读取
171
172
171


可见还是顺序读取较快! ConcurrentHashMap使用了segment 分段加锁,但是效率还是有一定损失!


但是这里存在的问题是, 并发修改时,两个线程读取的每个map都不一样,造成重复读取,执行双线程读取时,结果是:

poll 99415 elements!
poll 97851 elements!
Read last : 47 ms


但是实际一共只有100000 元素,因此无法保证同步性, 就像这篇文章说的:

http://www.cnblogs.com/zhuawang/p/4779649.html


Iterator对象的使用,不一定是和其它更新线程同步,获得的对象可能是更新前的对象,ConcurrentHashMap允许一边更新、一边遍历,也就是说在Iterator对象遍历的时候,ConcurrentHashMap也可以进行remove,put操作,且遍历的数据会随着remove,put操作产出变化,所以希望遍历到当前全部数据的话,要么以ConcurrentHashMap变量为锁进行同步(synchronized该变量),要么使用CopiedIterator包装iterator,使其拷贝当前集合的全部数据,但是这样生成的iterator不可以进行remove操作。


这种作法易产生同步问题!!! 而且还不如单线程的快!

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics