Alv*_*vin 22 java concurrency performance hashmap data-structures
我刚刚阅读了"清洁代码"一书,并发现了这一说法:
当Java年轻的时候,Doug Lea写了一本开创性的书[8] Java中的Concurrent Programming.随着这本书,他开发了几个线程安全的集合,后来成为了JDK的
java.util.concurrent一部分.该软件包中的集合对于多线程情况是安全的,并且它们表现良好.事实上,ConcurrentHashMap在 几乎所有情况下, 实现都比HashMap表现更好.它还允许同时并发读取和写入,并且它具有支持常见复合操作的方法,否则这些操作不是线程安全的.如果Java 5是部署环境,请从ConcurrentHashMap
请注意,在上面的引用中,我使用了"[n]",其中n是某个数字,表示作者提供引用的地方,正如您所看到的,他没有为粗体部分提供任何参考.
并不是说我不相信这个陈述,但我很想知道这个陈述的支持证据.因此,没有人知道,显示了两种性能统计信息的任何资源ConcurrentHashMap和HashMap?或者任何人都可以向我解释为什么ConcurrentHashMap比HashMap更快?
我可能会在休息时看看ConcurrentHashMap在工作中的实现,但是现在我想听听其他SOers的答案.
Ber*_*ann 11
如果您只使用单个线程访问HashMap,HashMap最快(它不会执行任何同步),如果您从多个线程访问它,ConcurrentHashMap比手动粗粒度同步更快.请看这里进行一些比较:
irr*_*ble 10
Doug Lea非常擅长这些事情,所以如果有一次他的ConcurrentyHashMap比Joshua Bloch的HashMap表现得更好,我也不会感到惊讶.但是从Java 7开始,HashMap的第一个@author也成了Doug Lea.显然现在HashMap没有理由比它的同伴堂兄慢.
出于好奇,我还是做了一些基准测试.我在Java 7下运行它.条目越多,性能越接近.最终ConcurrentHashMap在HashMap的3%范围内,这是非常了不起的.瓶颈实际上是内存访问,俗话说"内存是新磁盘(磁盘是新磁带)".如果条目在缓存中,则两者都会很快; 如果条目不适合缓存,则两者都会很慢.在实际应用程序中,映射不一定要与其他人竞争驻留在缓存中.如果经常使用地图,它会被缓存; 如果没有,它不会被缓存,这是真正的决定因素,而不是实现(两者都由同一专家实现)
public static void main(String[] args)
{
for(int i = 0; i<100; i++)
{
System.out.println();
int entries = i*100*1000;
long t0=test( entries, new FakeMap() );
long t1=test( entries, new HashMap() );
long t2=test( entries, new ConcurrentHashMap() );
long diff = (t2-t1)*100/(t1-t0);
System.out.printf("entries=%,d time diff= %d%% %n", entries, diff);
}
}
static long test(int ENTRIES, Map map)
{
long SEED = 0;
Random random = new Random(SEED);
int RW_RATIO = 10;
long t0 = System.nanoTime();
for(int i=0; i<ENTRIES; i++)
map.put( random.nextInt(), random.nextInt() );
for(int i=0; i<RW_RATIO; i++)
{
random.setSeed(SEED);
for(int j=0; j<ENTRIES; j++)
{
map.get( random.nextInt() );
random.nextInt();
}
}
long t = System.nanoTime()-t0;
System.out.printf("%,d ns %s %n", t, map.getClass());
return t;
}
static class FakeMap implements Map
{
public Object get(Object key)
{
return null;
}
public Object put(Object key, Object value)
{
return null;
}
// etc. etc.
}
Run Code Online (Sandbox Code Playgroud)
HashMap可能更慢的原因是因为它必须检测ConcurrentModification以知道何时抛出异常.ConcurrentHashMap不必检查modCount以知道何时抛出(但它确实将它用于size()和isEmpty()).获取锁是非常快的,尤其是在单线程情况下,当你已经持有锁时,但是检查modCount是两次读取和跳转 - 如果不相等HashMap必须支付以抛出CoModException.
我建议您阅读集合类的源代码,以便了解在进行方法调用时他们正在做多少工作.在只有字典获取/放置的完全私有映射的情况下,您通常可以使用剥离的HashMap而不使用任何modCount或甚至大小跟踪来提高性能.
这是一种很难以某种方式证明的橡胶声明.你如何衡量"几乎所有情况"?
A ConcurrentHashMap可能比同步更好HashMap.争论越多,差异就越显着.另一方面,由于在后一种情况下不必要的锁定的开销,非同步HashMap可能比a更快ConcurrentHashMap.
我也希望看到该陈述的背景,以及该书作者提出的支持它的证据.并且有关未使用的假设的证据表明哈希映射的"几乎所有"用例都涉及同步.
| 归档时间: |
|
| 查看次数: |
14136 次 |
| 最近记录: |