Java线程安全的只写hashmap [英] Java thread-safe write-only hashmap

查看:160
本文介绍了Java线程安全的只写hashmap的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的Java类中,我包含一个 Hashmap 变量(类属性),并运行一些只写入 HashMap 使用 put():每次写入时它都存储一个唯一的键(这是由设计完成的)。

同步关于只写方法的类方法是否足以满足安全条件?我的HashMap很简单,不是 ConcurrentHashMap

解决方案

仅仅同步写入是不够的。同步必须应用于读取和写入内存。



某些其他线程需要读取地图(否则,为什么需要地图?) ,并且该线程需要同步才能正确查看地图所代表的内存。为了提供一个假设的例子,假设线程1写入散列映射,这个散列映射就是这个映射状态中的瞬态不一致性的一部分。

其效果仅存储在CPU 1的1级缓存中 。然后,线程2有资格在几秒后运行,并在CPU 2上恢复;它读取来自CPU 2的1级缓存的散列映射 - 它看不到线程1写入的写入,因为 两者之间的写入和读取之间没有内存屏障操作 写作和阅读主题。即使线程1同步写入,尽管写入的效果将刷新到主内存,但线程2仍然不会看到它们,因为读取来自1级缓存。因此,同步写入操作只能防止写入冲突。

除了CPU缓存之外,JMM还允许线程私下缓存数据,这些数据只需要刷新到内存屏障的主内存(同步,具有一些特殊限制的易失性,或完成JMM 5+中不可变对象的构建)。



为了充分理解这个复杂的线程主题, 必须 研究和研究Java内存模型,用于在线程之间共享数据。您必须了解发生之前关系和内存可视性的概念,才能了解当今多CPU核心级别CPU缓存共享数据的复杂性。



如果您不想投入时间来理解JMM,那么简单的规则是两个线程必须在某处/以某种方式在写入和写入之间同步 在同一对象上 读取一个线程以查看其他操作的效果。期。请注意,这并不意味着对象的所有写入和读取都必须同步,本身;在一个线程中创建和配置一个对象,然后将其发布到其他线程是合理的,只要发布线程和获取线程在同一个对象上进行同步交换即可。


In my Java class I include a Hashmap variable (class property) and run some Threads which write-only into that HashMap using put(): each time the write happens it stores a unique key (which is done by design).

Is the synchronized keyword on a class method write-only sufficient for thead-safe conditions? My HashMap is simple and not a ConcurrentHashMap?

解决方案

No, it is not sufficient to only synchronize the writes. Synchronization must be applied to both reads and writes to memory.

Some other thread, somewhere, sometime, will need to read the map (otherwise, why have a map?), and that thread needs to be synchronized to correctly view the memory represented by the map. They also need to be synchronized to avoid tripping over transient inconsistencies in the map state as it's being updated.

To provide a hypothetical example, suppose Thread 1 writes the hashmap, the effects of which are stored in CPU 1's level 1 cache only. Then Thread 2, becomes eligible to run a few seconds later and is resumed on CPU 2; it reads the hashmap, which comes from CPU 2's level 1 cache - it does not see the writes that Thread 1 made, because there was no memory barrier operation between the write and the read in both the writing and the reading thread. Even if Thread 1 synchronizes the writes, then although the effect of the writes will be flushed to main memory, Thread 2 will still not see them because the read came from level 1 cache. So synchronizing writes only prevents collisions on writes.

Besides the CPU caching the JMM allows threads to cache data privately themselves which only has to be flushed to main memory at a memory barrier (synchronize, volatile with some special limitations, or completion of construction of an immutable object in JMM 5+).

To fully understand this complex subject of threading you must research and study the Java Memory Model, and it's implications for sharing data between threads. You must understand the concepts of "happens-before" relationships and memory visibility to understand the complexities of sharing data in today's world of multicore CPUs with various levels of CPU caching.

If you don't want to invest the time to understand the JMM, the simple rule is that two threads must somewhere/somehow synchronize on the same object between the writes and the reads for one thread to see the effects of the operations of the other. Period. Note that this doesn't mean that all writes and reads on an object must be synchronized, per se; it is legitimate to create and configure an object in one thread and then "publish" it to other threads, as long as the publishing thread and fetching thread(s) synchronize on the same object for the hand over.

这篇关于Java线程安全的只写hashmap的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆