[英]synchronized LinkedList - peek
LinkedList
有方便的peek
, pop
,...方法。
不幸的是,我需要一个线程安全的LinkedList
。 所以,我的第一个想法是将它包装如下:
List<Object> list = Collections.synchronizedList(new LinkedList<>());
但是,由于List
接口不包含peek
或pop
方法。 这当然不起作用。
或者,我可以在整个代码中使用synchronized(list)
块。 这是要走的路吗?
我忽视的任何解决方案?
编辑:
人们使用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();
}
}
这提出了一个问题,因为有一段时间你的列表可以在peek
和pop
之间进行更改(上面代码中的这个地方被标记为“Problem”)。
检查和修改的正确方法是在单个synchronized
块中进行,即
synchronized(list) {
String s = list.peek();
if (s != null) {
s = list.pop();
}
}
但是,这不能在简单的包装器中完成,因为在单个synchronized
块中执行了两个列表操作。
您可以通过构建自己的封装LinkedList<T>
的数据结构来避免在多个位置进行synchronized
编写,并提供在同步块中执行所有测试和修改操作的操作。 但是,这不是一个简单的问题,因此您最好以一种可以使用预定义并发容器之一的方式更改算法。
你想要的是并发Queue
。 LinkedList
实现List
, Deque
和Queue
。 Queue
是通过peek和pop赋予它FIFO(在后面添加,从前面删除)语义的原因。
LinkedBlockingQueue可以是有界的,这是您的标准之一。 还有其他几个并发队列和Deques可供选择。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.