代码之家  ›  专栏  ›  技术社区  ›  ashitaka

ConcurrentLinkedQueue poll()是否会阻止?

  •  2
  • ashitaka  · 技术社区  · 16 年前

    我的线程将永远运行,并在ConcurrentLinkedQueue Peek()之后调用ConcurrentLinkedQueue poll()。

    但在某些情况下,线程似乎挂起了。我知道这有点含糊 但是人们能为我确认方法poll()或peek()将 从未 块。谢谢。

    3 回复  |  直到 16 年前
        1
  •  2
  •   bruno conde    16 年前

    据我所知, ConcurrentLinkedQueue 是“无等待”实现。

    所以我必须假设每个独立的呼叫 poll() peek() 决不阻止 .

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

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

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

    不是这样吗? obj 不会 null .

        2
  •  0
  •   basszero    16 年前

    根据JavaDoc,似乎peek()和poll()永远不会阻塞。我做了一个快速的生产者/消费者测试,没有遇到任何阻碍。

        3
  •  0
  •   Rasmus Faber    16 年前

    我不认为你的问题是因为这个,但是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()将被阻塞,直到它们可以确定队列是否为空。

    但是,除非您使用一些非常奇怪的线程优先级,否则这种情况是 高度地 不太可能,我建议你到别处找你的bug。