从数组中同时读取是否线程安全?

10

我有一个包含整数值的数组,声明如下:

int data[] = new int[n];

每个值都需要被处理,我正在将工作分成几个部分,以便可以由不同的线程进行处理。在处理期间数组不会被修改。

所有处理线程是否可以同时读取数组的不同部分?还是说我需要使用锁?

换句话说:这个工作顺序是线程安全的吗?

Array is created and filled
Threads are created and started
Thread 0 reads data[0..3]
Thread 1 reads data[4..7]
Thread 2 reads data[8..n]

任意数量的线程可以读取值。只有涉及写入时,关键部分才会起作用。 - Jyro117
@Jyro117 或者其他读者!遍历结构体应该进行同步。 - William Morrison
如果您的结构被视为不可变的,即内部数据或结构本身没有写入操作,那么您无需对其进行同步。除非在读取时结构发生更改,但在数组的情况下永远不会发生。 - Jyro117
@WilliamMorrison,这个问题怎么会和你找到的重复呢?这是一个不同的情况。 - Dariusz
6个回答

6

如果多个线程读取数组(或任何其他集合、对象的字段等)的内容,只要数据在此期间没有被修改,则是线程安全的。

如果您填充了要处理的数据并将其传递给不同的线程进行读取,则数据将被正确读取,并且不会发生数据竞争。

请注意,仅当您填充数组后创建线程时,此方法才有效。如果您未经同步即将数组传递给某些已存在的线程进行处理,则可能无法正确读取数组的内容。在这种情况下,线程获取数组引用的方法应该被同步,因为同步块强制在线程之间进行内存更新。

顺便提一下:使用不可变集合可能是一个好主意。这样可以确保根本没有修改。我建议使用这样的包装器。检查java.util.concurrent.atomic包,应该有您可以使用的东西。


谢谢您的快速回复。我想知道是否也可能反过来,即线程可以同时写入。(这些线程永远不会写入相同的索引) - user2342875
@user2342875 你的意思是写入吗?如果你从不同的线程写入到不同的内存位置,如果你不使用同步,你永远无法确定内存是否会被正确地(带有新值)从不同的线程读取。同步还确保了线程之间的内存同步。 - Dariusz
@user2342875 我重新修改了我的回答,并提到了一个潜在的陷阱,请在你的代码中考虑它。 - Dariusz

2
只要线程不修改数组中的内容,多个线程从数组中读取数据是没有问题的。

0

如果您确保所有线程只是读取,那么它就是线程安全的。尽管您不应该仅依赖于这一点,并尝试通过包装器使您的数组不可变。


0

当然,如果你只是想读取它,那么在创建线程时将数组传递给它们即可。只要不修改它,就不会有任何问题。


0

从数组中读取是线程安全的操作,但如果您要修改数组,请考虑使用类AtomicIntegerArray


0
考虑填充一个 ConcurrendLinkedQueue,并让每个线程从中取出。这将确保不存在并发问题。
您的线程将从队列顶部拉取其数据并进行处理。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接