synchronized LinkedList - peek

时间:2015-11-20 16:46:31

标签: java linked-list thread-safety peek

LinkedList方便的peekpop,...方法。

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

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

但是,由于List界面不包含peekpop方法。当然,这不起作用。

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

我忽视的任何解决方案?

修改

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

更多背景资料:

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

2 个答案:

答案 0 :(得分:4)

如果您需要peek工作,那么制作同步包装可能还不够,因此您必须明确地编写synchronized

编写包装器并不是一个问题,因为它是peek方法的语义问题。与表示单个操作的pop方法不同,peek方法通常用于由peek组成的多组件操作,然后根据{{1}执行其他操作返回。

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

peek

这会出现问题,因为您的列表可能会在String s; synchronized(list) { s = list.peek(); } // <<== Problem ==>> if (s != null) { synchronized(list) { s = list.pop(); } } peek之间发生变化(以上代码中的此位置标记为&#34;问题&#34 ;)

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

synchronized

但是,这不能在一个简单的包装器中完成,因为在一个synchronized(list) { String s = list.peek(); if (s != null) { s = list.pop(); } } 块中执行了两个列表操作。

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

答案 1 :(得分:2)

您想要的是并发QueueLinkedList实施ListDequeQueueQueue是使用peek和pop赋予它FIFO(在后面添加,从前面删除)语义的原因。

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