操作不同的数组(对象数组)索引时是不是需要同步

Posted

技术标签:

【中文标题】操作不同的数组(对象数组)索引时是不是需要同步【英文标题】:Is synchronization needed when manipulating different array(object array) indices操作不同的数组(对象数组)索引时是否需要同步 【发布时间】:2009-06-02 15:14:36 【问题描述】:

在Java的上下文中,我有这样的代码,

MyObject[] array;

在不同的线程中我有这样的代码

array[i] = new MyObject(val);

如果我确保我的每个线程都使用不同的“i”值,那么我是否需要同步上述语句来处理竞争条件?

【问题讨论】:

如果每个线程使用不同的“i”值,为什么要共享同一个数组?每个线程都可以使用它自己的数组... 【参考方案1】:

只有当两个线程可以同时读取和修改同一个变量时,竞争条件才是一个问题。

只要您确定每个线程使用不同范围的索引,并且没有重新定义底层数组,那么将每个单元格视为不同的变量应该是安全的。因此,每个线程都在一组单独的变量上工作,您不会遇到竞争条件。

话虽如此,请确保您在使用索引时确实没有重叠 - 这通常比看起来更棘手。

此外,您必须确保没有两个单元格映射到对象中 - 如果您从两个线程修改同一个对象(而不仅仅是对它的引用),您可能会遇到竞争条件。

【讨论】:

【参考方案2】:

也许吧。如果每个任务都写入数组中的不同位置,它们不会覆盖彼此的输出。这样就行了。

但是,在最终处理数组时,您可能会遇到问题,因为 Java 不保证值何时写入内存。优化器可能决定写的太晚了(或者对你来说太晚了)。因此,您应该将数组设置为volatile,这意味着在访问其中的值时不必进行缓存。

【讨论】:

关于 VM 何时将值写入内存的要点 - “发布”的概念很棘手 但是,对于给定线程,IT 写入其位置的值将始终是 IT 随后读取的值。 volatile 的问题与实际数组 reference. 的发布有关 @Neil:你确定数组中的数据会在线程间及时更新吗?据我了解这个问题,子线程写入数据,然后主线程对其进行处理。子线程如何确保数据在主线程看到的内存中? @Aaron:我认为你误解了 Niel 的评论(我同意)他并没有声称任何同步行为,只是孩子写的就是孩子看到的。 @Stu:尼尔所说的是正确的,但在原始问题的上下文中没有帮助。 volatile 仅适用于数组引用;我不确定如何强制 Java 将其应用于单个数组元素,或者 Java VM 模型是否包含针对这种情况的任何保证。【参考方案3】:

如果您绝对确定每个线程将始终访问不同的索引,那么您不需要同步这些访问。

但您确实需要确保对数组的引用正确发布到不同的线程——实际上这通常意味着引用需要是@ 987654321@或volatile。

【讨论】:

【参考方案4】:

这里有三个谨慎的同步兴趣点。

数组变量本身: 将变量array 声明为volatilefinal(或在array 上同步)很重要,这样可以保证两个线程都访问同一个实例大批。如果没有,以下是可能的:

    线程 A 和 B 启动 线程 A 将 array 实例化为新的 Array 对象 线程 B 尝试访问线程 A 的 array,但得到 NullPointerExceptoin 因为它还没有看到线程 A 将新数组分配给 array

不好。

对 MyObject 实例的数组引用(这似乎是 Venkatraman 的实际问题):随着 array 变量本身正确同步,那么 是的,两个线程可以访问不同的元素在数组中安全。一旦子线程完成了它正在做的事情,那么“主”线程将想要同步数组以确保它在使用它们之前获得子数组元素的最终状态。

MyObject 实例本身,但这似乎超出了问题的范围

【讨论】:

以上是关于操作不同的数组(对象数组)索引时是不是需要同步的主要内容,如果未能解决你的问题,请参考以下文章

js 对象操作

JavaScript数组的简单介绍

检查数组对象中特定索引的所有值是不是为 Null?

js基础_数组简介

两个空对象(空数组)为什么不相等

php数组转json对象并保留数字索引