• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Paul Clapham
  • Ron McLeod
  • Tim Cooke
  • Junilu Lacar
Sheriffs:
  • Rob Spoor
  • Devaka Cooray
  • Jeanne Boyarsky
Saloon Keepers:
  • Jesse Silverman
  • Stephan van Hulst
  • Tim Moores
  • Carey Brown
  • Tim Holloway
Bartenders:
  • Jj Roberts
  • Al Hobbs
  • Piet Souris

Some Questions Pertaining to the ConcurrentModificationException

 
Ranch Hand
Posts: 113
1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I will be much obliged if someone is able to assist me with answers to a few questions on the code below. Before I pose the questions, I provide the following notes about the code:

(1.) The code spawns a couple of threads (in addition to the thread spawned to execute the main method) and each thread processes/accesses nonconcurrent collections (i.e., an ArrayList and a HashMap).

(2.) The main method’s thread and each of the other two threads modify the collections while iterating over them using an enhanced for loop.

(3.) When the three threads mentioned in point number 2 above modify a nonconcurrent collection in an enhanced for loop, the ConcurrentModificationException gets either thrown or not, as follows:

(A.) The exception gets thrown when the main method’s thread modifies the nonconcurrent collection in the loop.

(B.) The exception does not get thrown when both of the other two threads together modify the nonconcurrent collection in the loop.

(C.) The exception does not get thrown when either of the other two threads alone modifies the nonconcurrent collection in the loop.

(4.) Depending on what lines in the code get commented out, the program execution may or may not throw the ConcurrentModificationException.

(5.) Certain lines of the program will need to be commented out, in order to check out various behaviors that I inquire about in the questions that I ask about the code.

(A.) For example, in order to check out the program behavior when only one thread is spawned (in addition to the main method’s thread), either line 32 or 33 needs to be commented out.

(B.) The lines that are currently commented out in the code are those that potentially cause the throwing of the ConcurrentModificationException.
The following are the questions I have:

(1.) Why does the ConcurrentModificationException not get thrown when multiple threads together modify a noncurrent collection while iterating over it in an enhanced for loop, but the exception gets thrown when the single main method’s thread does this? Even if the program structure, in which multiple threads modify a noncurrent collection, is not a loop (e.g., even if it is a simple sequence structure), my understanding is that this exception needs or should be thrown, i.e., if such a nonconcurrent collection is being modified by multiple threads non-thread-safely; furthermore, as I understand, a way to preclude the throwing of this exception is by replacing the nonconcurrent collection with a concurrent one, thereby enabling the multiple threads to thread-safely modify the replacement concurrent collection. Is this understanding that I have inaccurate?

(2.) Since the ConcurrentModificationException gets thrown when a single thread (i.e., the single main method’s thread) modifies a collection while iterating over it using an enhanced for loop, why doesn’t the exception get thrown when either of the other two threads alone does this?
 
Sheriff
Posts: 22504
122
Eclipse IDE Spring VI Editor Chrome Java Windows
  • Likes 2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
This exception is horribly misnamed. It gets thrown in just one situation - if you are using an Iterator (or ListIterator), and are modifying the backing collection or map through any means other than the (List)Iterator. It doesn't matter if you do it concurrently or not, as you have seen. A better name would have been ModificationOutsideIteratorException, or something like that.

Some concurrent collections use techniques that prevent this, but not all. CopyOnWriteArrayList does this by using a snapshot to iterate over; if the list is modified, the snapshot stays intact. You're actually iterating over something that may be out-of-date. Vector on the other hand does not prevent this, and will still throw a ConcurrentModificationException.
 
Rob Spoor
Sheriff
Posts: 22504
122
Eclipse IDE Spring VI Editor Chrome Java Windows
  • Likes 2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
As for why the threads don't throw an exception - they do. You just don't see it. Add a try-catch block in your run method to see this:

Executors apparently swallow any exceptions thrown from their tasks. That's pretty annoying...
 
Nyeng Gyang
Ranch Hand
Posts: 113
1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks for what I find to be a useful response.
 
Rob Spoor
Sheriff
Posts: 22504
122
Eclipse IDE Spring VI Editor Chrome Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
You're welcome.
 
Master Rancher
Posts: 4052
56
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Rob Spoor wrote:It gets thrown in just one situation - if you are using an Iterator (or ListIterator), and are modifying the backing collection or map through any means other than the (List)Iterator.


That's not true, really.  Looking at ArrayList as an example, there are other situations that can result in a ConcurrentModificationException without any use of an Iterator.  As an example, if you call add() while equals() is running.  However, I think that all the other cases are probably impossible in single-threaded code.  You've identified the most commonly encountered cause, and the only one I know of that can happen with single threading.
 
Rob Spoor
Sheriff
Posts: 22504
122
Eclipse IDE Spring VI Editor Chrome Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
You're right. I should have said "if you're iterating". equals, hashCode, toArray and the bulk calls (containsAll, addAll, removeAll, removeIf, retainAll) usually all have hidden iterations. Some are even implemented with an Iterator; in Java 8, equals and hashCode also used an Iterator.
 
You showed up just in time for the waffles! And this tiny ad:
Building a Better World in your Backyard by Paul Wheaton and Shawn Klassen-Koop
https://coderanch.com/wiki/718759/books/Building-World-Backyard-Paul-Wheaton
reply
    Bookmark Topic Watch Topic
  • New Topic