java - 同步链表 - peek

标签 java linked-list thread-safety peek

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

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

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

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

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

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


编辑:

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

更多背景信息:

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

最佳答案

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

与其说是编写包装器的问题,不如说是 peek 的语义问题。方法。不同于 pop方法,表示单个操作,peek方法常用于由peek组成的多组件 Action 中-然后根据什么做其他事情peek返回。

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

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

这会带来一个问题,因为有时您的列表可能会在 peek 之间发生变化。和 pop (上面代码中的这个地方被标记为“问题”)。

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

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

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

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

关于java - 同步链表 - peek,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33831871/

相关文章:

java - 如何使用证书和私钥在 Java 中签署 XML 文档?

java - 用Java实现一对多映射

java - 错误: incompatible types: Object cannot be converted to Trees

c# - 多线程进程中静态 Queue.Enqueue 期间意外数据丢失

ios - tableView 更新期间对数据源的线程安全访问

java - 准备好的语句失败

java - 如何从远程服务器的 Shell 脚本运行 java -jar 命令?

java - 如何将节点添加到倒数第二个位置?

C++使用链表、模板和栈设计一个大整数加减法的类

引用的 C++ 复制省略