synchronized LinkedList - peek



LinkedList具有方便的peekpop。。。方法

不幸的是,我需要一个线程安全的LinkedList。因此,我的第一个想法是将其包装如下:

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

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

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

有没有我忽略的解决方案?


编辑:

使用LinkedList的原因有很多。我看到有些人在提议其他的收藏品。因此,这里遵循简短的要求,这导致我决定使用LinkedList

更多背景信息:

  • 我正在使用LinkedList,因为这些项目需要订购
  • 应以非阻塞方式添加项目
  • 项目添加在后面;从前面拆下
  • 在移除第一个项目之前,首先需要对其进行peek编辑和验证。如果验证失败,则该项目需要保留在列表中
  • 只有验证成功完成,才会删除第一个项目
  • 队列需要具有最大大小(以避免内存问题)

如果您需要peek来工作,那么制作一个同步的包装器可能是不够的,因此您必须显式地编写synchronized

与其说是编写包装器的问题,不如说是peek方法的语义问题。与代表单个操作的pop方法不同,peek方法通常用于由peek-ing组成的多组件操作,然后根据peek返回的内容执行其他操作。

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

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

这是一个问题,因为有时您的列表可以在peekpop之间更改(上面代码中的这个位置标记为"问题")。

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

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

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

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

您想要的是一个并发的QueueLinkedList实现ListDequeQueueQueue赋予了它带有peek和pop的FIFO(添加到后面,从前面移除)语义。

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

相关内容

  • 没有找到相关文章

最新更新