同时修改HashMap的条目是否安全...如果地图的大小是固定的并且条目是链接列表?

时间:2013-04-30 00:51:47

标签: java concurrency linked-list hashmap

我目前有链接列表的固定大小的HashMap,我想知道通过调用get()然后修改该链表的内容来修改两个DIFFERENT键的值是否安全(添加/减去节点和东西)?我知道由于可能的调整大小问题同时修改不同的密钥是不安全的,但是1)散列图的大小是固定的,链接列表都是从头开始初始化(作为空列表)和2)我怀疑在像这样的情况HashMap会存储指向链表的指针,因此修改列表实际上不会修改HashMap的内容,但我不能确定。

任何更熟悉Java的人都能回答这个问题吗?我之所以没有使用线程安全的数据结构,是因为我的项目规范禁止它。谢谢!

3 个答案:

答案 0 :(得分:3)

这应该没问题,因为地图实际上是只读的。您可能希望在使用Collections.unmodifiableMap或Guava的ImmutableMap初始化时强制执行此操作。

链接列表是另一回事,除非您可以保证对每个列表的单线程访问。如果没有,快速解决方案是在创建时使用Collections.synchronizedList包装每个列表。或者您可以使用ConcurrentLinkedQueue代替。

答案 1 :(得分:1)

  

我开始使用线程安全数据结构的原因是因为我的项目规范禁止它。

嗯......他们要你做的是使用Java的低级同步原语实现你自己的同步。

这与在非同步数据结构上执行非同步操作不同。


记录:

  • 如果您正在阅读/更新列表,则需要同步。
  • 即使是“有效不可变”的数据结构也需要安全发布,以避免潜在的内存危害。
  • 如果您在一个线程中创建数据结构并尝试在另一个线程中使用它,则存在潜在问题......除非“创建”和“使用”操作之间存在先发生关系。 (如果父线程在子线程上调用start()之前创建/初始化数据结构,那就足够了......)

答案 2 :(得分:0)

在没有同步的情况下同时修改任何数据,即使是单个布尔字段也是不安全的。 “Java Concurrency in Practice”中的黄金法则:每当多个线程访问给定的状态变量,并且其中一个可能写入它时,它们都必须使用同步协调对它的访问。 < / p>