Win a copy of Functional Reactive Programming this week in the Other Languages forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Concurrent Modification Exception: CopyOnWriteArrayList or ArrayList.Clone()

 
Raghav Viswanathan
Greenhorn
Posts: 26
Chrome Eclipse IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello Greenhorns,

few days back I faced an exception "java.util.ConcurrentModificationException"

We get this error similar to the scenario desribed below



The catch is that I have say a global list where I keep adding values when there is a change of property.

The way to solve this would be to
1. Clone the global list and use the cloned list for iteration
2.Use CopyOnWriteArrayList

I presonally prefer the CopyOnWriteArrayList because,

It creates a copy only when we would run into Concurrent modification

But am not able to substantiate my claim. Could anyone please help out on the understanding of the best solution and why one is better than the other?.
 
Tony Docherty
Bartender
Posts: 2989
59
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
But am not able to substantiate my claim. Could anyone please help out on the understanding of the best solution and why one is better than the other?.

The API docs for CopyOnWriteArrayList say:

"This is ordinarily too costly, but may be more efficient than alternatives when traversal operations vastly outnumber mutations, and is useful when you cannot or don't want to synchronize traversals, yet need to preclude interference among concurrent threads."

So if you do many traversals and not many modifications it may be suitable and the other hand if you do many modifications and not many traversals it probably isn't.
Personally I wouldn't expose the list to other objects and so I would be able to suitable provide synchronization within the declaring class. There are many ways of doing this and the most efficient depends on the amount of data in your list and how you predominantly use the list. If performance is of the essence then you will probably have to try a few solutions and use a profiler to determine which is the most efficient.
 
Campbell Ritchie
Sheriff
Pie
Posts: 50251
79
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Why on earth are you using the add method while you have an Iterator object in scope?
 
Raghav Viswanathan
Greenhorn
Posts: 26
Chrome Eclipse IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks Tony for your Reply.

Campbell Ritchie,

The following is a scenario that closely represents the way its implemented.

1. I have a global list of String (Screen field names for which some modfication has happened)
1.1 In a scenario, I have a String (StringObject1) which has been modified by the user on screen.
1.2 The modified element has a rule that suggests that if StringObject1= "Some Value" then StringObject2 will take "New Value".
1.3 In this case First, the list of modified element (global list that is maintained) is first iterated and each element in the list is processed to check for rules.
1.4 The Rule in Point 1.2 is triggered, thus modifying the value of StringObject2.
1.5 When ever a value is modified, the element is added to the global list.
1.6 at the next point of next iteration I run into ConcurrentMod.

I know this sounds silly and would be complex. If at all this needs to be refactored, it would mean a complete redesign. The fix to this problem seems to be either CopyOnWrite or Clone. Please suggest.
 
Campbell Ritchie
Sheriff
Pie
Posts: 50251
79
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You don’t need to refactor anything. You simply need to use the Iterator correctly. If you need to add something, use a for loop rather than an Iterator.
 
Campbell Ritchie
Sheriff
Pie
Posts: 50251
79
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Are you sure you won’t end up adding "3"s until you run out of memory?
 
Raghav Viswanathan
Greenhorn
Posts: 26
Chrome Eclipse IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:Are you sure you won’t end up adding "3"s until you run out of memory?


I dont think so . Because,
1. (for ArrayList) :the Iterator when it was created will have a length of 5 and new additions will cause Concurrentmodification

2. For CopyOnWriteArrayList: : The iterator retains a copy and when calling add, a new copy of array list is created and on that the add is performed. It does not affect the arraylist object associated to the iterator

The Code looks like this.




the output for the code would be ,


List Value:1
My Old List >>>>>>>>>>> [1, 2, 3, 4, 5]
List Value:2
My Old List >>>>>>>>>>> [1, 2, 3, 4, 5]
List Value:3
My Old List >>>>>>>>>>> [1, 2, 4, 5, 3]
List Value:4
My Old List >>>>>>>>>>> [1, 2, 4, 5, 3]
List Value:5
My Old List >>>>>>>>>>> [1, 2, 4, 5, 3]


If you need to add something, use a for loop rather than an Iterator
.
I did not understand this part. becasue even if i use a for-loop instead of an iterator, I would end up at ConcurrentModification error.

Thanks and regards,
Raghav.V
 
Campbell Ritchie
Sheriff
Pie
Posts: 50251
79
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
No Iterator, no exception. Iterate up to original size only. If you are deleting, you can use n-- to shorten the loop.
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic