同步与重入锁定的性能

use*_*erx 13 java multithreading

在针对多线程系统的Queue实现时,我遇到了一些惊喜.这是:-

场景: - 1个生产者,1个消费者: - 生产者将整数放入队列中.消费者只是将其从队列中删除.

队列的基础数据结构: - TreeSet(我从未想过会使用),LinkedList,LinkedBlockingQueue(具有不确定的大小)

代码: - TreeSet作为队列: -

while (i < 2000000) {
        synchronized (objQueue) {

            if (!(objQueue.size() > 0)) {
                try {
                    objQueue.wait();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            Integer x = objQueue.first();
            if (x != null) {
                objQueue.remove(x);
                ++i;
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

编辑:-

      while (i < 2000000) {
        synchronized (objQueue) {
            objQueue.add(i);
            ++i;
            objQueue.notify();
        }
    }
Run Code Online (Sandbox Code Playgroud)

对于LinkedBlockingQueue: -

     while (i < 2000000){
        try {
            objQueue.put(i);
            ++i;
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            Thread.currentThread().interrupt();
        }
    }

      while (i < 2000000) {
        try {
            objQueue.take();
            ++i;

        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            Thread.currentThread().interrupt();
        }
    }
Run Code Online (Sandbox Code Playgroud)

对于LinkedList: - 具有synchronized的类似代码.

问题: -

1)当我通过Visual VM测量性能时,我观察到生成器代码,TreeSet比LinkedBlockingQueue和LinkedList表现更好,即使它需要O(log n)时间,在Linked结构中创建对象也是一个重要的开销.为什么理论与实践有很大不同?为什么我们更喜欢队列实现中的Tree结构的Linked,Array结构?

2)同步作为ReeentrantLock的明显赢家出现,因为TreeSet比LinkedList表现更好,LinkedList表现优于LinkedBlockingQueue.我希望我可以附加Visual VM结果.它不是与文章一起投票,http://www.ibm.com/developerworks/java/library/j-jtp10264/index.html

执行操作

戴尔Vostro 1015,核心2双核2.10,2GB Ram,32位操作系统和

JVM:Java HotSpot(TM)客户端VM(20.1-b02,混合模式)Java:版本1.6.0_26,供应商Sun Microsystems Inc.

Kum*_*tra 19

1. ReentrantLock如果您需要实现遍历链表的线程,锁定下一个节点然后解锁当前节点,则可能更容易使用.

2. Synchronized关键词适用于锁定粗化等情况,通过逃逸分析提供自适应旋转,偏置锁定和锁定省略的可能性.ReentrantLock目前尚未实现这些优化.

要进行适当的性能比较,请参阅:

http://lycog.com/concurency/performance-reentrantlock-synchronized/

  • 链接的文章有一个巨大的错误 - 他的可重入锁定示例实际上并没有锁定. (9认同)
  • 库马尔忘记提到他从[David Dice的博客](https://blogs.oracle.com/dave/entry/java_util_concurrent_reentrantlock_vs)中得到答案. (2认同)

JB *_*zet 5

  1. 因为您的基准测试存在缺陷:在实际用例中,从队列中生成和使用元素所花费的时间比向队列添加元素和从队列中删除元素所花费的时间要重要得多.因此队列的原始性能并不那么重要.顺便说一下,代码只显示了如何从第一个队列实现中获取元素,而不是如何添加元素.而且,选择合适的结构不是基于性能,而是基于行为.如果你想要并发的东西,你选择一个阻塞队列,因为它是为你实现的,并没有像代码那样的bug.如果您想要FIFO(通常是您想要的),则不会选择TreeSet.

  2. 如果要比较synchronized和ReentrantLock,则不应将一个数据结构用于一个,另一个数据结构用于另一个.ReentrantLock曾经更快,但现在它们处于同一水平(如果我相信Brian Goetz在JCIP中所说的话).无论如何,出于安全/能力的原因,我会选择一个而不是另一个.不是出于性能原因.