这个函数是原子的吗?
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 顺序的多线程的情况。仅仅是因为您正在尝试并行处理有序数据,而不能保证以相同顺序完成处理。
如果碰巧绝对需要用户并行处理,您可以使用如下流行的线程配置:
- 您可以拥有一个管理器-工作器系统,其中管理器线程获取作业,并将其委托给工作线程池,工作线程池将根据某些 属性作业的数据结构(即时间戳、序列号)。
- 您可以有一个委托线程来获取作业,并将其委托给工作线程池,该线程池将进行处理并将结果提交给另一个线程,该线程将根据某些 属性 在作业的数据结构中(即时间戳、序列号)。
在 Manager 或 Output Sequencer 线程中,您可能必须维护数据缓冲区,这些缓冲区将在排序以进行调度之前保存数据。
如您所见,这样的实现可能非常复杂。所以你要问问自己,'do you really need to process the data in parallel?'。
我有一个用例,我需要向底层数据结构添加值并且需要维护顺序。我使用 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 顺序的多线程的情况。仅仅是因为您正在尝试并行处理有序数据,而不能保证以相同顺序完成处理。
如果碰巧绝对需要用户并行处理,您可以使用如下流行的线程配置:
- 您可以拥有一个管理器-工作器系统,其中管理器线程获取作业,并将其委托给工作线程池,工作线程池将根据某些 属性作业的数据结构(即时间戳、序列号)。
- 您可以有一个委托线程来获取作业,并将其委托给工作线程池,该线程池将进行处理并将结果提交给另一个线程,该线程将根据某些 属性 在作业的数据结构中(即时间戳、序列号)。
在 Manager 或 Output Sequencer 线程中,您可能必须维护数据缓冲区,这些缓冲区将在排序以进行调度之前保存数据。
如您所见,这样的实现可能非常复杂。所以你要问问自己,'do you really need to process the data in parallel?'。