-1

As we all know, iterating without synchronization on a collection risks throwing ConcurrentModificationException if another thread happens to concurrently modify the collection.

But what about calling size() on the collection? Does size() involve iteration to count the number of elements in the collection? If that is the case, ConcurrentModificationException may occur (some people report this, for example here, but for me it is not clear that size() was the culprit).

On the other hand, if size() just gets an internal int counter variable, no exception would occur.

Which one is the case?

HUMBLE EDIT: Thanks to the answerers for the precision that this depends on the implementation. I should have mentioned that it is a TreeMap. Can I have this problem with that map? The docs say nothing about TreeMap.size().

Community
  • 1
  • 1
ARX
  • 1,040
  • 2
  • 14
  • 20

2 Answers2

1

The docs don't explicitly state that a ConcurrentModificationException will occur if you invoke Collection#size.

The only real times it's thrown are described in ConcurrentModificationException itself:

This exception may be thrown by methods that have detected concurrent modification of an object when such modification is not permissible.

For example, it is not generally permissible for one thread to modify a Collection while another thread is iterating over it. In general, the results of the iteration are undefined under these circumstances. Some Iterator implementations (including those of all the general purpose collection implementations provided by the JRE) may choose to throw this exception if this behavior is detected. Iterators that do this are known as fail-fast iterators, as they fail quickly and cleanly, rather that risking arbitrary, non-deterministic behavior at an undetermined time in the future.

If you're really worried about this sort of thing, then be sure that the concrete implementation of your collection uses an approriate size() method, like ConcurrentLinkedQueue.

Returns the number of elements in this queue. If this queue contains more than Integer.MAX_VALUE elements, returns Integer.MAX_VALUE. Beware that, unlike in most collections, this method is NOT a constant-time operation. Because of the asynchronous nature of these queues, determining the current number of elements requires an O(n) traversal.

Additionally, if elements are added or removed during execution of this method, the returned result may be inaccurate. Thus, this method is typically not very useful in concurrent applications.

Makoto
  • 104,088
  • 27
  • 192
  • 230
1

It doesn't matter whether size() will throw ConcurrentModificationException. Almost no collections will throw that exception on size(), but that doesn't make it safe.

When you call size() on a collection that other threads modify, you're reading shared memory. If the collection you're using doesn't offer specific synchronization guarantees and you're not using other synchronization mechanisms, the value you read could be arbitrarily out of date, or it could even correspond to a program state that you would think "hasn't happened yet".

user2357112
  • 260,549
  • 28
  • 431
  • 505