简体   繁体   English

我应该在阅读时同步共享资源(可变)吗?

[英]Should I synchronise on shared resource (mutable) while reading?

I have a HashMap which is shared among multiple threads.我有一个在多个线程之间共享的 HashMap。 And any thread can update it.任何线程都可以更新它。 So I synchronise on HashMap object while updating it.所以我在更新时同步 HashMap object 。

Should I synchronise while reading too?我也应该在阅读时同步吗? OR just making it volatile is enough?或者只是让它变得不稳定就足够了?

Note: I know I could simply use ConcurentHashMap but want to know whether multi threading affects reading of shared resources which are mutable.注意:我知道我可以简单地使用 ConcurentHashMap 但想知道多线程是否会影响对可变共享资源的读取。 If yes, how it affects ?如果是,它如何影响

Also what if it is a simple object (not a collection) or a primitive type.另外,如果它是简单的 object(不是集合)或原始类型怎么办。

You need to synchronise while reading too, or switch to using a ConcurrentHashMap.您也需要在阅读时进行同步,或者切换到使用 ConcurrentHashMap。

If one thread calls the get method while another thread is updating the map, it is impossible to predict what will happen.如果一个线程调用get方法,而另一个线程正在更新 map,则无法预测会发生什么。 The get method may throw an exception, because it assumes that the internal structure of the map does not change while it's running. get方法可能会抛出异常,因为它假定 map 的内部结构在运行时不会发生变化。

The Java HashMap documentation states (bolding in the original): Java HashMap文档状态(原文加粗):

Note that this implementation is not synchronized.请注意,此实现不同步。 If multiple threads access a hash map concurrently, and at least one of the threads modifies the map structurally, it must be synchronized externally.如果多个线程同时访问hash map,并且至少有一个线程在结构上修改了map,则必须对外同步。 (A structural modification is any operation that adds or deletes one or more mappings; merely changing the value associated with a key that an instance already contains is not a structural modification.) This is typically accomplished by synchronizing on some object that naturally encapsulates the map. (结构修改是添加或删除一个或多个映射的任何操作;仅更改与实例已包含的键关联的值不是结构修改。)这通常通过在自然封装 map 的某些 object 上同步来完成. If no such object exists, the map should be "wrapped" using the Collections.synchronizedMap method.如果不存在这样的 object,则应使用 Collections.synchronizedMap 方法“包装” map。 This is best done at creation time, to prevent accidental unsynchronized access to the map:这最好在创建时完成,以防止对 map 的意外非同步访问:

 Map m = Collections.synchronizedMap(new HashMap(...));

The iterators returned by all of this class's "collection view methods" are fail-fast : if the map is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove method, the iterator will throw a ConcurrentModificationException .所有此类的“集合视图方法”返回的迭代器都是快速失败的:如果 map 在创建迭代器后的任何时间进行结构修改,除了通过迭代器自己的 remove 方法之外,迭代器将抛出ConcurrentModificationException . Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.因此,面对并发修改,迭代器快速而干净地失败,而不是在未来不确定的时间冒任意的、非确定性的行为。

Note that the fail-fast behavior of an iterator cannot be guaranteed as it is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification.请注意,不能保证迭代器的快速失败行为,因为一般来说,在存在不同步的并发修改的情况下,不可能做出任何硬保证。 Fail-fast iterators throw ConcurrentModificationException on a best-effort basis.快速失败的迭代器会尽最大努力抛出ConcurrentModificationException Therefore, it would be wrong to write a program that depended on this exception for its correctness: the fail-fast behavior of iterators should be used only to detect bugs.因此,编写一个依赖于这个异常的正确性的程序是错误的:迭代器的快速失败行为应该只用于检测错误。

You can not safely change a HashMap while reading from it.在读取HashMap时,您无法安全地更改它。 Can you safely climb a ladder while rungs are being removed?当梯级被移除时,你能安全地爬梯子吗?

You should also synchronize the read side because any guarantees (visibility in your case) applies only when threads uses same lock, so when you skip synchronizing while reading - it means that reading thread doesn't use the same lock (it doesn't use any lock) which will lead to see stale values by reading thread.您还应该同步读取端,因为任何保证(在您的情况下的可见性)仅在线程使用相同的锁时适用,因此当您在读取时跳过同步时 - 这意味着读取线程不使用相同的锁(它不使用任何锁),这将导致通过读取线程看到陈旧的值。 See here: Should getters and setters be synchronized?请参阅此处: getter 和 setter 是否应该同步?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 我应该在Java 8 Streams中使用共享的可变变量更新吗? - Should I use shared mutable variable update in Java 8 Streams 我应该让对象变得可变吗? - Should I make the object mutable? 在不同线程中同时更新(或/和读取)共享可变 object 的不同字段 - Updating (or/and reading) different fields of a shared mutable object in different threads concurrently 深度克隆,同时保留对可变对象的共享引用 - Deep-cloning while preserving shared references to mutable objects 在阅读 CSV 时,我应该更喜欢 FileReader 而不是 BufferedReader? - Should I prefer FileReader to BufferedReader while reading CSV? 我应该使用什么来跟踪Java中可变对象的详细信息 - what should I use to track details of mutable objects in java 我应该在可能的情况下最终设置对可变对象的引用吗? - Should I set references to mutable objects final when possible? findWithinHorizo​​n会继续读取,但应该失败 - findWithinHorizon keeps reading while it should fail 在Java中读取属性文件时,我应该使用try-catch还是引发自定义异常,或者两者都使用? - Should I use try-catch or throws custom exception or both while reading property file in Java? ListView元素背景-资源mutable() - ListView element background - resource mutable()
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM