Sorry Paul but all this does is endorse the second camp: they want structural and content modifications to trigger CME. Further it assumes that doing a replaceAll while an iterator is active is always an error which need not be the case. CME is about the safety of the implementation, not the semantics of concurrent observation.

Also it is not just a "belief" that CME is only for structural modifications on ArrayList, it is clearly specified as such.

Cheers,
David

On 19/05/2018 7:25 AM, Paul Sandoz wrote:
Hi,

My CME budget is definitely in the red now :-) but i would like to attempt to 
summarize the different positions and suggest a solution. If that does not get 
traction i believe a graceful retreat is in order.

We appear to be in two different philosophical camps with regards to the 
interpretation of modCount (i suspect what both camps believe is compatible 
with what CME specifies [*]).

One camp believes AbstractList.modCount should only (on a best-effort basis) be 
incremented on structural modifications that change the size (even if the size 
change cannot be externally observed, like the example Doug presents).

The other camp believes there are other forms of modification that perturb the 
list leading to incorrect results since those forms can affect yet to be 
traversed elements. It is argued that bulk operations such as replaceAll and 
sort fit in this category, regardless of the implementation.

I hope that is an accurate representation, and if that is so here is a rough 
proposal bring those camps together. The specification of AbstractList.modCount 
could be modified as follows:

/**
  * The number of times this list has been <i>structurally modified</i>
  * or <i>globally modified</i>.
  * Structural modifications are those that change the size of the
  * list, or otherwise perturb it in such a fashion that iterations in
  * progress may yield incorrect results.
  * Global modifications are those where the size may not change but the
  * list is perturbed as a whole in such a fashion that iterations in progress
  * may yield incorrect results.

Thoughts?

Paul.

[*] on CME
* Note that this exception does not always indicate that an object has
* been concurrently modified by a <i>different</i> thread.  If a single
* thread issues a sequence of method invocations that violates the
* contract of an object, the object may throw this exception.  For
* example, if a thread modifies a collection directly while it is
* iterating over the collection with a fail-fast iterator, the iterator
* will throw this exception.
*
* <p>Note that fail-fast behavior cannot be guaranteed as it is, generally
* speaking, impossible to make any hard guarantees in the presence of
* unsynchronized concurrent modification.  Fail-fast operations
* throw {@code ConcurrentModificationException} on a best-effort basis.
* Therefore, it would be wrong to write a program that depended on this
* exception for its correctness: <i>{@code ConcurrentModificationException}
* should be used only to detect bugs.</i>


On May 16, 2018, at 4:04 PM, Doug Lea <d...@cs.oswego.edu> wrote:


Sorry Stuart, but I'm joining the no-modCount barrage.
To pick on the main issue...

On 05/16/2018 05:21 PM, Stuart Marks wrote:

Suppose that a replaceAll() on another thread occurs, and that this is
allowed. Does the application care whether the eventual printout
contains partly new values and partly old values? How can you tell? It
seems to me that this is more likely a programming error than a valid
use case.

There are many data-races that are never detected via CME. CME was
designed to trap only some of them (and even at that, only heuristically
because modCount operations are not strictly ordered). ModCount
mechanics only deal with insertions and removals. Failing to catch a
race in replaceAll is no different than failing to catch one with
multiple concurrent setValues. It might be "nice" to adjust modCount on
any operation that might contribute to a datarace, but no reason to
single out replaceAll.

Having said this, I don't think that anything in the spec (vs default
implementation) prohibits an implementation of replaceAll from removing
and then re-inserting each element, in which case an implementation
would modify modCounts.

-Doug


Reply via email to