同步链表 - peek

synchronized LinkedList - peek

一个LinkedList方便的peekpop、...方法。

不幸的是,我需要一个thread-safeLinkedList。所以,我的第一个想法是将其包装如下:

List<Object> list = Collections.synchronizedList(new LinkedList<>());

但是,由于 List 接口不包含 peekpop 方法。这当然行不通。

或者,我可以在整个代码中使用 synchronized(list) 块。这是要走的路吗?

我忽略了任何解决方案吗?


编辑:

使用 LinkedList 的原因有很多。我看到有人在提议其他 collections。所以,这里遵循简短的要求,这导致我决定使用 LinkedList.

更多背景信息:

如果您需要 peek 工作,制作一个同步包装器可能不够,所以您必须明确地写 synchronized

与其说是编写包装器的问题,不如说是 peek 方法的语义问题。与表示单个动作的 pop 方法不同,peek 方法通常用于由 peek 组成的多组件动作,然后根据 [=12] 执行其他操作=] returns.

如果在包装器中同步,结果将与手动编写此代码相同:

String s;
synchronized(list) {
    s = list.peek();
}
// <<== Problem ==>>
if (s != null) {
    synchronized(list) {
        s = list.pop();
    }
}

这会带来一个问题,因为有时您的列表可能会在 peekpop 之间变化(上面代码中的这个位置被标记为 "Problem" ).

进行检查和修改的正确方法是在单个 synchronized 块中进行,即

synchronized(list) {
    String s = list.peek();
    if (s != null) {
        s = list.pop();
    }
}

但是,这不能在简单的包装器中完成,因为两个列表操作在单个 synchronized 块中执行。

您可以通过构建自己的封装 LinkedList<T> 的数据结构来避免在多个地方写入 synchronized,并提供在同步块中执行所有测试和修改操作的操作。但是,这不是一个简单的问题,因此您最好以一种可以与预定义的并发容器之一一起工作的方式更改算法。

你要的是并发QueueLinkedList 实现了 ListDequeQueueQueue 赋予它 FIFO(在后面添加,从前面删除)语义,带有 peek 和 pop。

A LinkedBlockingQueue 可以有界,这是你的标准之一。还有其他几个并发队列和双端队列可供选择。