is Java HashSet thread-safe for read only?

痴心易碎 提交于 2019-12-20 09:29:47

问题


If I have an instance of an HashSet after I ran it through Collections.unmodifiableSet(), is it thread-safe?

I'm asking this since Set documentation states that it's not, but I'm only performing read operations.


回答1:


From the Javadoc:

Note that this implementation is not synchronized. If multiple threads access a hash set concurrently, and at least one of the threads modifies the set, it must be synchronized externally

Reading doesn't modify a set, therefore you're fine.




回答2:


HashSet will be threadsafe if used in a read-only manner. That doesn't mean that any Set that you pass to Collections.unmodifiableSet() will be threadsafe.

Imagine this naive implementation of contains that caches the last value checked:

Object lastKey;
boolean lastContains;

public boolean contains(Object key) {
   if ( key == lastKey ) {
      return lastContains;
   } else {
      lastKey = key;
      lastContains = doContains(key);
      return lastContains;
   }
}

Clearly this wouldn't be threadsafe.




回答3:


It would be thread safe, but only owing to the fact that Collections.unmodifiableSet() internally publishes the target Set in safe manner (via the final field).

Note that in general statements such as "read-only objects are always thread-safe" are not correct, since they don't take into account possibility of operation reordering.

It's (theoretically) possible that, due to operation reordering, a reference to that read-only object will become visible to other threads before object is completely initialized and populated with data. To eliminate this possibility you need to publish references to the object in safe manner, for example, by storing them in final fields, as it's done by Collections.unmodifiableSet().




回答4:


Every data structure is thread-safe if you don't mutate it.

Because you have to mutate a HashSet in order to initialize it, it is necessary to synchronize once between the thread which initialized the set and all reading threads. You have to do it only one time. For example when you pass the reference to the unmodifiable set to a new thread which never touched it before.




回答5:


I don't believe it is thread safe just because you run Collections.unmodifiableSet(). Even though the HashSet if fully initialized and you marked it as unmodifiable, doesn't mean that those changes will be visible to other threads. Even worse, in the absence of synchronization, a compilier is allowed to re-order instructions, which could mean that not only does a reading thread see missing data but it can also see the hashset in a wierd state. Therefore you will need some synchronization. I believe one way around this is to create the hashset as final and to fully initialize it in the constructor. Here is a good article on the JMM http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html. Read the section on How do final fields work under the new JMM?

The ability to see the correctly constructed value for the field is nice, but if the field itself is a reference, then you also want your code to see the up to date values for the object (or array) to which it points. If your field is a final field, this is also guaranteed. So, you can have a final pointer to an array and not have to worry about other threads seeing the correct values for the array reference, but incorrect values for the contents of the array. Again, by "correct" here, we mean "up to date as of the end of the object's constructor", not "the latest value available".




回答6:


Yes, it is safe for concurrent read access. Here is the relevant sentence from the documentation:

If multiple threads access a hash set concurrently, and at least one of the threads modifies the set, it must be synchronized externally.

It states that you only need to synchronize if at least one thread modifies it.




回答7:


If the shared memory will never be changed, you can always read without synchronizing. Making the set unmodifiable will just enforce the fact that no writes can be made.



来源:https://stackoverflow.com/questions/5379794/is-java-hashset-thread-safe-for-read-only

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!