【问题标题】:Will ConcurrentLinkedQueue#poll() ever block?ConcurrentLinkedQueue#poll() 会阻塞吗?
【发布时间】:2009-02-19 11:42:11
【问题描述】:

我的线程永远运行并在 ConcurrentLinkedQueue#peek() 之后调用 ConcurrentLinkedQueue#poll()。

但在某些情况下,线程似乎挂起。我知道这有点模糊 但是人们可以为我确认 poll() 或 peek() 方法将 NEVER 阻塞。谢谢。

【问题讨论】:

  • 请发布您的代码/单元测试,以便我们运行并验证代码的某些方面没有导致问题

标签: java concurrency


【解决方案1】:

据我所知,ConcurrentLinkedQueue 是一个“无需等待”的实现。

所以我必须假设每个对poll()peek() 的独立调用都将永远不会阻塞

对这个集合的原子操作是同步的,并且每个单独的队列调用都保证线程安全。

您的代码一定有问题。例如,如果你这样做:

Object obj;

if (queue.peek() != null)
   obj = queue.poll()

不保证obj 不会是null

【讨论】:

    【解决方案2】:

    根据 Javadoc,peek() 和 poll() 似乎永远不应该阻塞。我进行了快速的生产者/消费者测试,没有遇到任何阻塞。

    【讨论】:

      【解决方案3】:

      我不认为你的问题是因为这个,但是 poll() 和 peek() 可以(至少理论上)阻塞:

      顾名思义,ConcurrentLinkedQueue 是作为链表实现的。在轮询或窥视时,实现尝试从头部开始并遍历链接的节点,试图找到一个没有被删除的节点。如果找到一个非空节点,则返回该节点,如果到达末尾,则返回队列为空,但如果找到已删除的节点,则重试。

      所以考虑这个顺序。 P是生产者线程,我们有两个消费者线程C1和C2:

      P:  queue.add()
      C1: starts queue.poll(), begins to inspect first node
      C2: completes a queue.poll() removing the item.
      P:  queue.add()
      C1: continues inspecting the first node, notes that it is deleted. 
            Restarts and begins to inspect the new first node.
      C2: completes a queue.poll() removing the item.
      P:  queue.add()
      C1: continues inspecting the first node, notes that it is deleted. 
            Restarts and begins to inspect the new first node.
      etc.
      

      所以 poll() 和 peek() 会阻塞,直到它们可以确定队列是否为空。

      但除非您使用一些非常奇怪的线程优先级,否则这种情况不太可能发生,我建议您在别处寻找错误。

      【讨论】:

        猜你喜欢
        • 2011-11-04
        • 2016-10-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多