【问题标题】:ConcurrentLinkedDeque vs LinkedBlockingDequeConcurrentLinkedDeque vs LinkedBlockingDeque
【发布时间】:2013-10-04 10:29:07
【问题描述】:

我需要一个线程安全的 LIFO 结构,并发现我可以为此使用Deque 的线程安全实现。 Java 7 引入了ConcurrentLinkedDeque,Java 6 引入了LinkedBlockingDeque

如果我只使用LinkedBlockingDeque 中的非阻塞方法,例如addFirst()removeFirst(),它与ConcurrentLinkedDeque 有什么区别吗?

即如果不考虑阻塞方面,ConcurrentLinkedDequeLinkedBlockingDeque 之间除了LinkedBlockingDeque 有界之外还有其他区别吗?

【问题讨论】:

  • 您是否查看了两者的实现?你的标准是什么,你会在哪里做出决定?表现?内存开销?
  • 我只是想知道如果我继续使用 Java 6 并使用 LinkedBlockingDeque 会丢失什么

标签: java multithreading data-structures concurrency


【解决方案1】:

引用伟大的Doug Lea(我的重点)

LinkedBlockingDeque vs ConcurrentLinkedDeque

LinkedBlockingDeque 类旨在成为“标准”阻塞双端队列类。当前实现开销相对较低,但可扩展性相对较差。 ...

... ConcurrentLinkedDeque 具有与 LinkedBlockingDeque 几乎相反的性能配置文件开销相对较高,但可扩展性非常好。 ...在并发应用程序中,想要一个线程安全但不支持阻塞的 Deque 并不常见。而大多数这样做的人可能会更好地使用特殊情况的解决方案。

他似乎在建议您应该使用LinkedBlockingDeque,除非您特别需要ConcurrentLinkedDeque 的功能。

【讨论】:

  • 请注意,他在 2004 年非正式地说过。
【解决方案2】:

ConcurentLinkedDequeue 是无锁的(参见源代码中的 cmets),而 LinkedBlockingQueue 使用锁定。那就是前者应该更有效率

【讨论】:

    【解决方案3】:

    两件事:

    1:如果我只使用LinkedBlockingDeque 中的非阻塞方法,例如addFirst()removeFirst(),与ConcurrentLinkedDeque 有什么区别吗?

    这些方法在并发锁定行为方面确实存在差异,在LinkedBlockingDeque

    public E removeFirst() {
            E x = pollFirst();
            ..
        }
     public E pollFirst() {
            lock.lock(); //Common lock for while list
            try {
                return unlinkFirst();
            } finally {
                lock.unlock();
            }
        }
    

    addFirst 方法类似。在ConcurrentLinkedDeque 中,这两种方法的锁定行为是不同的,并且更有效,因为它不会锁定整个列表而是锁定其中的一个子集,检查ConcurrentLinkedDeque 的源将使您更清楚这一点。

    2:来自ConcurrentLinkedDeque的javadoc:

    请注意,与大多数集合不同,size 方法不是 恒定时间操作。

    ..

    另外,批量操作addAll、removeAll、retainAll、 containsAll、equals 和 toArray 不保证执行 原子地。

    以上不适用于LinkedBlockingDeque

    【讨论】:

    • addAll 等在 LinkedBlockingQueue 中也是非原子的。它使用迭代器反复获取和释放锁
    【解决方案4】:

    首先,LinkedBlockingDeque 和 ConcurrentLinkedDeque 都是线程安全的,但使用哪一个取决于您的应用程序要求。

    例如,

    LinkedBlockingDequeue :如果您希望一次只有单个线程可以对您的数据进行操作,并且当您的应用程序需要阻塞时,请使用此集合。

    ConcurrentLinkedDeque:这也是线程安全的集合双端队列,如果您的应用程序是多线程的,并且您希望您的每个线程都可以访问数据,那么 ConcurrentLinkedDequeue 是最好的选择。 p>

    正如你的问题,

    1.我需要一个线程安全的 LIFO 结构,

    如果您希望只有单个线程可以操作您的数据,请使用 LinkedBlockingDeque。

    如果您希望每个线程都可以访问共享数据,请使用 ConcurrentLinkedDeque

    2。如果忽略阻塞方面,ConcurrentLinkedDeque 和 LinkedBlockingDeque 之间是否还有其他区别,

    是的,LinkedBlockingDeque 使用的是锁定机制,而 ConcurrentLinkedDeque 不是,这可能会影响您想要操作数据时的性能。

    【讨论】:

      猜你喜欢
      • 2017-10-13
      • 2013-07-14
      • 1970-01-01
      • 2018-12-23
      • 2016-06-28
      • 2014-08-17
      • 2011-09-18
      • 1970-01-01
      相关资源
      最近更新 更多