这个函数是原子的吗?

Is this function atomic?

我有一个用例,我需要向底层数据结构添加值并且需要维护顺序。我使用 ConcurrentLinkedQueue 作为底层数据结构。以下是函数

public void put(V value) {
   concurrentLinkedQueue.add(value); 
}

这个语句是原子的吗,如果两个线程试图放入值,首先是线程 A(值 V1),然后是线程 B(值 V2),是否有可能先添加 V2,然后再添加 V1 .

答案是你的问题有点无意义。

如果两个线程以非同步方式调用 put,那么

之间没有明显的区别
Thread 1     Thread 2

put          
add
             put
             add

Thread 1    Thread 2

put          
             put
             add
add

即使您使用 synchronized 方法,您的程序中也会出现数据竞争,除非您在两个操作之间引入适当的先行发生关系。

问问自己 为什么 线程调用的顺序 put 很重要,并确保通过适当的同步捕获此意图。

背景:ConcurrentLinkedQueue在实现中是线程安全的。这是先进先出。所以它将维护插入顺序。

您问题的答案:

Is this statement atomic

Is there a possibility V2 will be added first and V1 later

如果您希望线程 A 在线程 B 之前插入值,则需要实现例程来显式处理插入顺序。 ConcurrentLinkedQueue 中添加操作的原子性与它无关。这完全取决于哪个线程首先调用 add() 方法。

如果你想保持顺序(即 - FIFO),多线程可能不是你的答案。请问为什么需要多线程执行?我可以想到一些你需要使用 FIFO 顺序的多线程的情况。仅仅是因为您正在尝试并行处理有序数据,而不能保证以相同顺序完成处理。

如果碰巧绝对需要用户并行处理,您可以使用如下流行的线程配置:

  1. 您可以拥有一个管理器-工作器系统,其中管理器线程获取作业,并将其委托给工作线程池,工作线程池将根据某些 属性作业的数据结构(即时间戳、序列号)。

  1. 您可以有一个委托线程来获取作业,并将其委托给工作线程池,该线程池将进行处理并将结果提交给另一个线程,该线程将根据某些 属性 在作业的数据结构中(即时间戳、序列号)。

在 Manager 或 Output Sequencer 线程中,您可能必须维护数据缓冲区,这些缓冲区将在排序以进行调度之前保存数据。

如您所见,这样的实现可能非常复杂。所以你要问问自己,'do you really need to process the data in parallel?'。