If fail-safe iterator creates a separate copy and works on that, how come it is aware of any changes made to the original?
public class concurrentHashMap {
public static void main(String[] args) throws InterruptedException {
MapCheck obj1 = new MapCheck();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
obj1.put();
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
obj1.iterte();
}
});
t1.start();
t2.start();
t1.join();
t2.join();
}
}
class MapCheck {
Map<Integer,String> map = new ConcurrentHashMap<>();
{
map.put(1, "pujan");
map.put(2, "manish");
map.put(3, "swati");
}
void iterte() throws InterruptedException {
for (int key : map.keySet()) {
Thread.sleep(2000);
System.out.println(map.get(key));
}
}
void put() throws InterruptedException{
Thread.sleep(2000);
map.put(1, "pujan1");
map.put(2, "manish1");
map.put(3, "swati1");
}
}
The output is:
pujan1
manish1
swati1
The Fail fast iterator aborts the operation as soon it exposes failures and stops the entire operation. Comparatively, Fail Safe iterator doesn't abort the operation in case of a failure. Instead, it tries to avoid failures as much as possible.
Fail-fast and Fail-safe are the concepts of concurrent modification. Concurrent modification is a process in which an object is modified concurrently when a different task is running over it. Fail-fast and Fail-safe are the iterators to iterate over the Collection objects.
Iterator of ConcurrentHashMap is fail-safe, it means that it doesn't throw ConcurrentModificationException even if underlying ConcurrentHashMap is modified once Iteration begins.
If the Iterator detects any structural change after iteration has begun e.g adding or removing a new element then it throws ConcurrentModificationException, this is known as fail-fast behavior and these iterators are called fail-fast iterator because they fail as soon as they detect any modification.
There is no such thing as a "fail-safe" iterator in Java. At least, the Java SE specifications do not define such a term. I therefore recommend that you avoid using the term "fail-safe" to describe Java iterators.
I'm well aware that various articles on the Internet and elsewhere on Stack Overflow use the term "fail-safe", but their usage is not definitive, and it's likely to be incorrect or at the very least misleading. I believe you've been misled by such documentation.
It sounds like you read somewhere that a "fail-safe" iterator works on a separate copy. In your example, you use a ConcurrentHashMap
, which indeed has iterators that aren't fail-fast. However, CHM's iterators don't operate on a copy. Instead, they have semantics that are described by the official specification as weakly consistent. The definition is somewhat abstruse, but essentially, any element reported by such an iterator is guaranteed to have existed in the collection at some point in time. These kind of iterators might or might not reflect changes to the collection that were made after the iteration started. That's why the thread that's running the iterator sees changes made by the other thread. (It's also possible for some or none of the changes to be visible, since these threads have a data race.)
An example of another collection whose iterators are not fail-fast is CopyOnWriteArrayList. This collection's iterators operate on a snapshot, so any subsequent changes to the collection are never visible via an iterator.
For completeness, here is the definition of a fail-fast iterator from the ArrayList
specification. Most of the other (non-concurrent) collections in Java have a fail-fast iteration policy that's defined similarly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With