Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8203704

remove increment of modCount from ArrayList and Vector replaceAll()

    XMLWordPrintable

    Details

    • Type: CSR
    • Status: Draft
    • Priority: P4
    • Resolution: Unresolved
    • Fix Version/s: tbd
    • Component/s: core-libs
    • Labels:
      None
    • Subcomponent:
    • Compatibility Kind:
      behavioral
    • Compatibility Risk:
      minimal
    • Compatibility Risk Description:
      Unlikely that anyone is depending on ConcurrentModificationExceptions being thrown
    • Interface Kind:
      Java API

      Description

      Summary

      ArrayList.replaceAll and Vector.replaceAll should not modify modCount, since they are not "structural modifications".

      Problem

      ArrayList#replaceAll increments modCount, but ArrayList subList#replaceAll does not.

      Vector#replaceAll increments modCount, but Vector subList#replaceAll (inherited from AbstractList and List) does not.

      ArrayList#replaceAll increments modCount, but the analogous HashMap#replaceAll does not.

      List#replaceAll is specified and implemented in terms of List#set, which does not modify modCount in any implementation.

      The List spec could be clearer, but the intent is that only operations that cause an object to "lose its place" in the List (modify its index) should cause ConcurrentModificationException. So element insertion and deletion cause ConcurrentModificationException, but replacing an element via List#set or ListIterator#set does not. Method replaceAll is logically just a call to List#set on every element, and the default implementation in List#replaceAll in fact does call List#set. "Structural modification" is a property that does compose over a series of operations.

      There are valid uses of replaceAll that should not break concurrent readers, e.g. a periodic call to Vector.replaceAll(x -> optimized(x)). In such a scenario incrementing modCount introduces a rare race instead of detecting one.

      The List interface is concurrency-hostile precisely because the mapping from index to element can change. But if a List is used in such a way that this cannot happen, array-style (like AtomicReferenceArray), then concurrent use becomes quite reasonable. Especially if there is only one writer thread.

      Solution

      Remove modCount++ statements in the source code.

      Specification

      No spec changes, although the existing spec for modCount and "structural modification" could be improved in a separate effort (JDK-8203663).

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              martin Martin Buchholz
              Reporter:
              smarks Stuart Marks
              Reviewed By:
              David Holmes, Doug Lea
              Votes:
              0 Vote for this issue
              Watchers:
              10 Start watching this issue

                Dates

                Created:
                Updated: