我有一个用例,我需要在底层数据结构中添加值,并且需要维护订单。我使用ConcurrentLinkedQueue
作为基础数据结构。以下是功能
public void put(V value) {
concurrentLinkedQueue.add(value);
}
这个语句是否是原子的,在某种意义上,如果两个线程试图放置值,线程A第一个(值V1)和线程B第二个(值V2),是否有可能首先添加V2,稍后添加V1。 / p>
答案 0 :(得分:3)
答案是你的问题毫无意义。
如果两个线程以不同步的方式调用put
,则
Thread 1 Thread 2
put
add
put
add
和
Thread 1 Thread 2
put
put
add
add
即使您使用方法synchronized
,您的程序中也会有数据竞争,除非您在两个操作之间引入了适当的先发生关系。
问自己为什么线程调用put
的顺序很重要,并确保通过适当的同步捕获此意图。
答案 1 :(得分:1)
背景:ConcurrentLinkedQueue
在实现中是线程安全的。它是FIFO。因此它将保持插入顺序。
您的问题的答案:
此声明是否为原子
是
是否有可能首先添加V2,稍后添加V1
是
如果希望线程A在线程B之前插入值,则需要实现例程以显式处理插入顺序。 ConcurrentLinkedQueue
中添加操作的原子性与此无关。这完全取决于哪个线程首先调用add()方法。
如果你想保持秩序(即 - FIFO),多线程可能不是你的答案。请问为什么需要多线程执行?我可以想到一些情况,你需要使用FIFO顺序进行多线程处理。只是因为您试图并行处理有序数据,而这些数据无法保证以相同的顺序完成处理。
如果绝对有必要使用并行处理,您可以使用如下的流行线程配置:
在Manager或输出序列发生器线程内部,您可能必须维护数据缓冲区,这些数据缓冲区将在排序之前保存数据以进行分派。
正如您所看到的,这样的实现可能非常复杂。所以你必须问自己,'你真的需要并行处理数据吗?'。