Why do I get a ConcurrentModificationException even though I do not edit anything?

I am trying to convert some serial code into some 'nice' multithreaded code, but when I try to run it, I get a java.util.ConcurrentModificationException of the iterator from the point I get more than 200 elements in the Set I'm iterating over. I thought you could only get this exception if you tried modifying something you're trying to acces/iterate over or vice versa, but I am not changing anything.

The example I'm talking about iterates over the keySet of a TreeMap and the code looks as follows:

private static SortedMap<BigInteger,Long> algorithm7(int n, 
        final SortedMap<BigInteger, Long> S, ExecutorService pool) {

    final SortedMap<BigInteger,Long> S1 = new TreeMap<BigInteger, Long>();
    final SmallAntiChain alfa = SmallAntiChain.universeAntiChain(n);
    final SmallAntiChain u = SmallAntiChain.universeAntiChain(n+1);
    final SmallAntiChain l = SmallAntiChain.singletonAntiChain(n+1);

    Future<?>[] list = new Future[S.size()];
    int i = 0;
    for (final BigInteger tCode : S.keySet()) {
        list[i++] = pool.submit(new Runnable() {

            @Override
            public void run() {
                SmallAntiChain t = SmallAntiChain.decode(tCode);
                Set<int[]> rtsymm = (t.join(l)).symmetryGroup();
                SortedMap<BigInteger, Long> St = new TreeMap<BigInteger, Long>();
                for (SmallAntiChain x : new AntiChainInterval(t.join(l),u.omicron(t, alfa))) {
                    BigInteger b = x.standard(rtsymm).encode(); 
                    Storage.store(St, b);
                }
                for (BigInteger b : St.keySet()) {
                    SmallAntiChain x = SmallAntiChain.decode(b);
                    BigInteger code = x.standard().encode();
                    Storage.store(S1,code,St.get(b)*S.get(tCode));
                }
            }

        });
    }

    try {
        for(Future<?> f : list)
            f.get();
    } catch (InterruptedException | ExecutionException e) {
        e.printStackTrace();
    }

    return S1;
}

with the calling method looking like:

public static SortedMap<BigInteger, Long>[] equivalenceClasses(int till, ExecutorService... pools) throws SyntaxErrorException {
    if(pools.length < 1)
        pools = new ExecutorService[]{ Executors.newFixedThreadPool(1) };
    @SuppressWarnings("unchecked")
    SortedMap<BigInteger, Long>[] reS = new TreeMap[till+1];
    reS[0] = new TreeMap<BigInteger,Long>();
    Storage.store(reS[0],SmallAntiChain.emptyAntiChain().standard().encode());
    Storage.store(reS[0],SmallAntiChain.emptySetAntiChain().standard().encode());
    int n = 0;
    while (n < till) {
        reS[n+1] = algorithm7(n,reS[n], pools[0]);
        n++;
    }
    return reS;
}

Could anybody tell me why I get the exception and what I could do to solve this problem? Preferably without having to use ConcurrentSkipListMap or having to change anything in the signature.

Thanks in advance


Edit: completed code and added the calling method as well

Upvotes: 2

Views: 668

Answers (1)

Ioannis Deligiannis
Ioannis Deligiannis

Reputation: 2719

According to the Java specification, get(..) should not throw a ConcurrentModificationException if the SortedMap has not been structurally modified. As you have not provided the full code, the only thing I can suggest is to wrap the SortedMap with Collections.unmodifiableSortedMap(S s) after you create it. This will throw an Exception if you have missed code that structurally modifies the Map.

Even if the code you provided does not modify the SortedMap, this doesn't exclude that an external(out of method)thread does not modify it.

Upvotes: 3

Related Questions