Reputation: 9579
I have been reading "Effective Java" Item 60, which is "Favor the use of standard exceptions".
Another general-purpose exception worth knowing about is ConcurrentModificationException. This exception should be thrown if an object that was designed for use by a single thread or with external synchronization detects that it is being concurrently modified.
Normally people face with CME
when they try remove from a collection while looping.
But in here I am interested about what would be a concise example on detecting a concurrent modification on self-implemented class object?
I expect it to be something like synchronizing on internal object and related boolean flag, if another thread confronts the flag being false, then throwing exception.
For a simple research I have found in source of ArrayList
:
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
but the principle behind how modCount
is maintained. I cannot find where it is being decremented.
Upvotes: 3
Views: 797
Reputation: 101
So, the general approach is following: just remember current state of your object and check its state every time when trying to access the object, if state changed, throw your exception!
Upvotes: 0
Reputation: 3821
As for how you would implement this kind of behaviour yourself: Your class depends on some assumptions to work properly, which could be violated if access to an object is not synchronized properly. Try to check those assumptions and throw a CME if you find that they are not true.
In the example of ArrayList
, the assumption is that nobody will change the structure of the list while you are iterating over it, so ArrayList
keeps track of a modification count that is not supposed to change during an iteration.
However, this checking is only there to make it more likely that a bad access will cause a clean exception instead of weird behaviour - in other words, this exception is just a help to developers and does not need to enforce correctness, because correctness is already compromised when you encounter it.
It is a good idea to offer this kind of help where it does not impact the performance of your class much, but using e.g. synchronization to ensure correct use is probably a bad idea - then you might as well make the class threadsafe to begin with.
This is why the API documentation for ArrayList
says:
Note that the fail-fast behavior of an iterator cannot be guaranteed as it is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification. Fail-fast iterators throw ConcurrentModificationException on a best-effort basis. Therefore, it would be wrong to write a program that depended on this exception for its correctness: the fail-fast behavior of iterators should be used only to detect bugs.
Upvotes: 2
Reputation: 500873
The modification count is essentially the "revision number" of the collection's state. It is incremented every time there is a structural change to the collection. It is never decremented.
When starting iteration, the iterator remembers the value of the mod count. It then periodically checks that the container's current mod count still equals the remembered value. If it doesn't -- meaning there has been a structural change since iteration began -- a ConcurrentModificationException
is thrown.
Upvotes: 3