在同步集合上同步 - >性能问题

时间:2012-05-02 00:03:59

标签: java

基于以下答案: 我还不清楚:如果有的话,concurrentMap上的synchronized构造会做什么。即,在并发映射的情况下,如果在同步(映射)与非同步之间存在差异,则有什么区别。 我对解决方案的正确性或相信的好处不感兴趣 。只是回答这个问题: 问:在并发映射上同步和不在同步映射上同步有什么区别?特别是关于性能..就足够了。没事了。
我只对所发生的事情感兴趣而且没有补充建议。

我有一个理论问题,我解决了一些心理问题: 假设我有一个Concurrent Collection类say => ConcurrentHashMap map;

假设我有三种方法:

method1: synchronized(map){
       doSomethingWithThemap(); //Assume put integers 1.. 1000000
}

method2:doSomethingWithThemap(); //Note it is not synchronized 
method3:doSomethingElseWithThemap(); //Assume put integers 2000000.. 3000000

现在假设2个TestCases:


  • TestCase1:产生两个线程A& B.调用method1和B调用method3。
  • TestCase2:产生两个线程A'& B”。 '调用method2和B'调用method3。

从性能的角度来看,我希望TestCase2能够获胜,因为根据我的理解,在TestCase1中B不能添加到地图中,尽管是并发的,因为synchronized块会锁定地图,这不是TestCase2中的情况。

我的单元测试不要验证这个假设。

问:我在这里错过了什么。即,并发收集的同步块是否会影响性能?

4 个答案:

答案 0 :(得分:2)

  问:我在这里缺少什么。

ConcurrentHashMap内部同步的假设不正确:根据the source code,实现使用java.util.concurrent.locks个对象,其实例隐藏在集合中,因此您无法锁定/同步它们。

一般来说,这是类库的编写者应遵循的建议:如果需要在对象上进行同步,请不要在this上进行同步;在类中创建一个私有对象,并在该对象上进行同步。否则,您可能会遇到由对象上的其他人同步引起的并发问题,并无限期地持有锁。

答案 1 :(得分:0)

您无法保证ConcurrentHashMap将其实例用作监视器。它可能会使用其他一些对象来锁定!

private Object lock = new Object();

synchronized(lock) {
   // do some stuff - you can't get my lock because it is private
}

ConcurrentHashMap甚至可能不使用锁,而是使用其他一些并发原语,如比较和设置,信号量等。

Java中的锁是可重入的,因此如果您已经锁定,则不会阻止自己。

答案 2 :(得分:0)

ConcurrentHashMap没有使用synchronized ...虽然仍然是线程安全的,但是get调用例如没有锁定任何东西。并发数据结构非常好用且有趣。那么它确实在某些情况下使用了一些内部锁定,但没有暴露任何东西,当然也没有暴露对象的监视器本身。

顺便说一下。像这样测量并发代码性能相当棘手,并且因运行和运行而异,但无论如何都是有缺陷的。

但是否则它理论上可以像你描述的那样使用同步的hashmap。 Collections.synchronizedMap(yourMap);

答案 3 :(得分:0)

What does the synchronized construct on the concurrentMap do, if anything

它只会浪费时间和空间。 ConcurrentMap已经体现了处理并发的替代方法。