Iterating over synchronized collection
Asked Answered
N

6

8

I asked here a question about iterating over a Vector, and I have been answered with some good solutions. But I read about another simpler way to do it. I would like to know if it is good solution.

synchronized(mapItems) {
    Iterator<MapItem> iterator = mapItems.iterator();
    while(iterator.hasNext())
        iterator.next().draw(g);
}

mapItems is a synchronized collection: Vector. Is that make the iterating over the Vector safe from ConcurrentModificationException?

Naturalist answered 15/3, 2013 at 17:48 Comment(1)
have you got any correct answer to accept??Otorhinolaryngology
P
3

Yes, it will make it safe from ConcurrentModificationException at the expense of everything essentially being single-threaded.

Peper answered 15/3, 2013 at 17:55 Comment(0)
K
2

Yes, I believe that this will prevent a ConcurrentModificationException. You are synchronizing on the Vector. All methods on Vector that modify it are also synchronized, which means that they would also lock on that same object. So no other thread could change the Vector while you're iterating over it.

Also, you are not modifying the Vector yourself while you're iterating over it.

Klondike answered 15/3, 2013 at 17:58 Comment(0)
L
2

Simply synchronizing the entire collection would not prevent a ConcurrentModificationException. This will still throw a CME

synchronized(mapItems) {
   for(MapItem item : mapsItems){
      mapItems.add(new MapItem());
   }
}
Logjam answered 15/3, 2013 at 18:25 Comment(0)
E
1

You may want to consider using a ReadWriteLock.

For processes which iterate over the list without modifying its contents, get a read lock on the shared ReentrantReadWriteLock. This allows multiple threads to have read access to the lock.

For processes which will modify the list, acquire the write lock on the shared lock. This will prevent all other threads from accessing the list (even read-only) until you release the write lock.

Embezzle answered 15/3, 2013 at 18:15 Comment(0)
G
1

Is that make the iterating over the Vector safe from ConcurrentModificationException?

YES It makes the iterating over Vector safe from ConcurrentModificationException.If it is not synchronized then in that case , if you are accessing the Vector via various threads and some other Thread is structurally modifying the Vector at any time after the iterator is created , the iterator will throw ConcurrentModificationException. Consider running this code:

import java.util.*;
class VVector 
{
    static Vector<Integer> mapItems = new Vector<Integer>();
    static
    {
        for (int i = 0 ; i < 200 ; i++)
        {
            mapItems.add(i);
        }
    }
    public static void readVector()
    {
        Iterator<Integer> iterator = mapItems.iterator();
        try
        {
            while(iterator.hasNext())
            {
                System.out.print(iterator.next() + "\t");
            }
        }
        catch (Exception ex){ex.printStackTrace();System.exit(0);}
    }
    public static void main(String[] args) 
    {
        VVector v = new VVector();
        Thread th = new Thread( new Runnable()
        {
            public void run()
            {
                int counter = 0;
                while ( true )
                {
                    mapItems.add(345);
                    counter++;
                    if (counter == 100)
                    {
                        break;
                    }
                }
            }
        });
        th.start();
        v.readVector();

    }
}

At my system it is showing following output while execution:

0       1       2       3       4       5       6       7       8       9
java.util.ConcurrentModificationException
        at java.util.AbstractList$Itr.checkForComodification(Unknown Source)
        at java.util.AbstractList$Itr.next(Unknown Source)
        at VVector.readVector(VVector.java:19)
        at VVector.main(VVector.java:38)

But on the other hand if you make the block of code containing Iterator to access that Vector synchronized using mapItems as lock , it will prevent the execution of other methods related to Vector until that synchronized block is completed atomically .

Gothurd answered 15/3, 2013 at 18:19 Comment(0)
O
0

if we invoke add method inside while loop then throws exception.

synchronized(mapItems) {
    Iterator<MapItem> iterator = mapItems.iterator();
    while(iterator.hasNext())
        iterator.next();
         mapItems.add("Something");  //  throws ConcurrentModificationException
}
Otorhinolaryngology answered 15/3, 2013 at 19:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.