1

With this code:

public class SynchroApp {

    public static void main(String[] args) {

        final List<String> unsyList = new ArrayList<>();
        final List<String> syList = Collections.synchronizedList(unsyList);

        TimerTask changeList = new TimerTask() {
            boolean addElem = false;

            @Override
            public void run() {
                // add / remove elements to keep size between 2 and 9
                if (syList.size() < 2)
                    addElem = true;
                else if (syList.size() > 8)
                    addElem = false;
                if (addElem)
                    syList.add(String.valueOf(System.currentTimeMillis()));
                else
                    syList.remove(0);
            }
        };

        TimerTask reverseList = new TimerTask() {
            @Override
            public void run() {
                try {
                    for (String s : syList)
                        s = new StringBuffer(s).reverse().toString();
                } catch (Exception e) {
                    System.out.println("Exception: " + e);
                }
            }
        };

        new Timer().scheduleAtFixedRate(changeList, 0L, 30L);
        new Timer().scheduleAtFixedRate(reverseList, 0L, 20L);
    }
}

Why do I still receive some ConcurrentModificationException on Iterator.next?

EDIT: the update of the list elements in reverseList wasn't working (as explained in comments). This code should work as expected:

for (int i = 0; i < syList.size(); i++)
    syList.set(i, new StringBuffer(syList.get(i)).reverse().toString());
9
  • I don't see a next call in that code you posted. Note, however that the loop in reverseList's run isn't doing anything at the moment (Java Strings are immutable). Commented May 2, 2014 at 11:49
  • 2
    You cannot use an iterator and, at the same time, modify the list's content. The iterator will realize that changes were made to the list and throw this exception. Commented May 2, 2014 at 11:50
  • 2
    @kviiri Even if the class was mutable it wouldn't do anything, as it uses a temporary variable. Commented May 2, 2014 at 11:52
  • 1
    next is implicit in (String s : syList). I think s is updated with the result of reverse(), but that's just an example anyway. Commented May 2, 2014 at 11:52
  • 1
    @Approachingminimums, yes, s is a reference to the list element, but you're not altering the element of the list but changing the (local) reference to refer to a whole different String altogether. Since Strings are immutable you need to remove the old String and add a new one to actually replace something. If Strings were mutable, you could do something like s.replace(...) but s = "something" still wouldn't work. Commented May 2, 2014 at 12:09

3 Answers 3

3

Because you're modifying the list while iterating on it.

Note that a synchronized list only makes each of its methods, and the methods of its iterator, synchronized. Iterating on a synchronized list is still a non-atomic operation, that involves several calls to synchronized methods. If you want to make the whole iteration atomic, you have to explicitely synchronize it, using the list itself as the lock:

synchronized (syList) {
    for (String s : syList) {
        s = new StringBuffer(s).reverse().toString();
    }
}
Sign up to request clarification or add additional context in comments.

Comments

1

Even most synchronized collections do not like modifications and iterator together. From the API description of Collections.synchronizedList:

It is imperative that the user manually synchronize on the returned list when iterating over it:

List list = Collections.synchronizedList(new ArrayList()); ... synchronized (list) { Iterator i = list.iterator(); // Must be in synchronized block while (i.hasNext()) foo(i.next()); }

Also: You can use the collections from java.concurrent instead. They usually have a more refined synchronization approach.

1 Comment

Thanks for the reference to the API documentation.
0

Both iterator and modifier has to use synchronizedList() in order to have proper locking/synchronization to be happened on the object.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.