在Java中,如果每个线程写入单独的单元空间,是否需要同步对数组的写入访问?
如果每个线程写入单独的单元空间,是否需要同步 Java 中数组的写入访问?
编辑:具体来说,该数组是原始数组或不可变对象数组。前任。 int 数组或 String 数组。
Is it required to synchronize write access to an array in Java if each thread writes to a separate cell space?
EDIT: Specifically, the array is either a primitive Array or an immutable object array. Ex. An int array or a String array.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
一般来说,是的。尝试使用矢量代替。
In general, yes. Try Vector instead.
我正要添加一个与此主题相关的问题。我做了一个测试,在访问数组时强制争用。两者都控制协调访问或使用非同步读取-修改-写入操作(如索引)。
当使用索引时——一些计数器> 1(全部应该为1,否则互斥破坏)
I was about to add a Question with this topic. I made a test that force contention while accessing an array. Both controlling coordinated access or with a non-synchronized read-modify-write operation like index--.
When using index-- some counters are > 1 (all should be 1, otherwise the mutual exclusion broke)
不要直接写入共享资源。你会让多线程程序的性能比单线程程序的性能更差。当缓存在块中被获取和失效时,缓存中的垃圾效应。如果您想了解更多信息,请看这个演讲。使用 volatile 和 Synchronize 比什么都不使用要好,但仍然很慢。
Don't write directly to a shared resource. Your gonna make the multi thread program perform worse than its single thread counter part. Trashing effect in Cache as Cache is fetched and invalidated in blocks. Do look at this talk if you want to know more. Use volatile and Synchronize its better than using nothing but still slow.
并发兴趣邮件列表提出了类似的问题 - “原子字节[]操作?”。
大卫·霍姆斯说:
Similar question posed to the Concurrency Interest mailing list - "Atomic byte[] operations?".
David Holmes said:
您可以执行您所要求的操作,更新每个索引所保存的内容,但不能保证读取索引中数据的其他线程正在看到当前数据。
Java 中有一个名为 易失性 的关键字,它标记实例和类变量,以便 JVM 知道这些值预计会发生变化,并且不会进行任何读取缓存优化,因为读取线程可能会过时数据。由于您无法将数组索引内容标记为
易失性
,因此其他读取器可能会获取过时的数据。在 Java 中使用原始数组仅在非常特定的场景中才是好的做法。您的情况可能是其中一种情况,但我无法从问题中看出,因此我建议您查看 java.util.concurrent 特别位于 CopyOnWriteArrayList 和 CopyOnWriteArraySet 如果您不想重复。
由于某种原因,它们现在已成为标准库的一部分,如果您正在进行大量线程和数据共享,您应该尽可能熟悉
java.util.concurrent
。You can do what you are asking, updating what each index holds, but you are not guaranteed that other threads reading the data in the indexes are seeing current data.
There is a keyword in Java called
volatile
that marks instance and class variables so that they JVM knows these values are expected to change and to not do any read cache optimization because the reading threads may get stale data. Since you can't mark array index contentsvolatile
other readers can get stale data.Using raw
Arrays
in Java is only good practice in very specific scenarios. Yours might be one of those cases, but I can't tell from the question, therefore I suggest you look at java.util.concurrent specifically at CopyOnWriteArrayList and CopyOnWriteArraySet if you don't want duplicates.These are part of the standard library for a reason now, and if you are doing heavy threading and data sharing you should be as intimately familiar with
java.util.concurrent
as possible.相同的线程是否也在读取该值。如果是这样那就没问题了。如果没有,那么您需要担心其他线程是否看到最新的值。这通常是通过关键工作 volatile 或通过原子变量来处理的。
如果这些线程也用于读取值那么你没问题,但如果一个新线程 -->线程 4 尝试读取值,则不能保证它会看到最新的分配。
如果你使用 AtomicIntegerArray、AtomicLongArray 或 AtomicReferenceArray 就可以了
Are the same threads also reading the value. If so then you are ok. If not then you need to worry about whether other threads see the most recent values. This is usually taken care of through the key work volatile or through atomics variables.
if these threads also are used to read the values then you are ok but if a new thread --> thread 4 attempts to read the values then there is no guarantee that it will see the latest assignment.
you'll be ok if you use AtomicIntegerArray, AtomicLongArray, or AtomicReferenceArray
如果您希望其他线程始终能够看到您写入的最后一个值,则通常需要同步。但我可能会在某些情况下,例如,预先计算一个非常昂贵的 long[] (其中每个条目都会占用大量 CPU),并且您会从多个线程执行此操作,知道这些线程中的任何两个都不得写入同一单元。然后,一旦所有线程完成,您将使用同步一次,以确保每个后续读取都会看到正确的值。类似的事情。
请注意,如果您不想自己处理同步问题,您可能需要研究像 AtomicLongArray 这样的类。作为一个额外的好处,像 AtomicLongArray 这样的类可能由不可能在 100% Java 中重新创建的实现支持。
You typically need to synchronize if you want other threads to be able to always see the last value you've written. But I could some cases where you'd be, say, precomputing a giganticly expensive long[] (where each entry would take a lot of CPU) and you'd be doing that from several threads, knowing no two of these threads shall write to the same cell. Then once all your threads would be done you'd be using synchronization once to be sure each subsequent read would see the correct values. Something like that.
Note that if you don't want to deal yourself with synchronization issues you may want to look into classes like AtomicLongArray. As an added benefit, classes like AtomicLongArray may be backed by an implementation that is impossible to re-create in 100% Java.
这不是一个简单的“是或否”问题。需要考虑的一些事情:
long
或double
值是不安全的double
或long
,由于缓存,其他线程可能无法立即看到更改的值(导致读取过时)Not a simple yes or no issue. Some things to consider:
long
ordouble
values is not safe without synchronizationdouble
orlong
, there is the possibility of another threads not being able to see changed values immediately because of caching (resulting in stale reads)如果读访问也以相同的方式分区,则不需要根据 bkail 的链接进行同步。
但是,如果线程读取彼此的写入,则仍然需要有内存屏障强制缓存内容同步。否则,threadys 可能会得到不一致的读取结果。
If read access is also partitioned in the same manner, then synchronization is not needed as per bkail's link.
But if the threads read each other's writes, it would still be necessary to have a memory barrier to force synchronization of cache contents. Otherwise, threadys may get inconsistent read results.
不,不需要同步。
它在 JLS §17.6 单词撕裂中定义:
No, synchronization is not needed.
It is defined in JLS §17.6 Word Tearing: