Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Concurrent Modification Exception #10

Closed
joerandazzo opened this issue Apr 29, 2015 · 9 comments · Fixed by #78
Closed

Concurrent Modification Exception #10

joerandazzo opened this issue Apr 29, 2015 · 9 comments · Fixed by #78

Comments

@joerandazzo
Copy link

Hello,

I noticed an older issue reporting ConcurrentModificationException, and found the issue is still occurring in 0.4.2. I tried keyset and entrySet.

    java.util.ConcurrentModificationException
            at java.util.LinkedHashMap$LinkedHashIterator.nextEntry(LinkedHashMap.java:350)
            at java.util.LinkedHashMap$EntryIterator.next(LinkedHashMap.java:379)
            at java.util.LinkedHashMap$EntryIterator.next(LinkedHashMap.java:377)
            at net.jodah.expiringmap.ExpiringMap$EntryLinkedHashMap$AbstractHashIterator.getNext(ExpiringMap.java:293)
            at net.jodah.expiringmap.ExpiringMap$EntryLinkedHashMap$EntryIterator.getNext(ExpiringMap.java:314)
            at net.jodah.expiringmap.ExpiringMap$EntryLinkedHashMap$EntryIterator.next(ExpiringMap.java:316)
            at net.jodah.expiringmap.ExpiringMap$EntryLinkedHashMap$EntryIterator.next(ExpiringMap.java:314)
@joerandazzo
Copy link
Author

And to be clearer, this is relating to setting the expiration policy to ACCESSED

@jhalterman
Copy link
Owner

Edit: If you do a map.get while iterating on a keySet with ExpirationPolicy.ACCESSED you will get ConcurrentModificationException since the get can effectively modify the map by removing expired elements. Instead, use entrySet:

for (Map.Entry<String, String> entry : map.entrySet()) {
  System.out.printf("key:" + entry.getKey() + " val:" + entry.getValue());
}

Let me know if you still have problems.

@MohdArshil
Copy link

MohdArshil commented May 27, 2019

Hello @jhalterman ,
Facing same error periodically in the following implementation.
Map<String, Object> map = ExpiringMap.builder().expiration(3600, TimeUnit.SECONDS).build(); List<Object> objList = new ArrayList<>(map.values());

Any Suggestion for the solution.

@jhalterman
Copy link
Owner

@MohdArshil Are you iterating over keys while attempting to modify the map? Or are you doing some other operations?

@egg82
Copy link

egg82 commented Jul 26, 2019

ConcurrentMap provides two contracts:

  1. Thread safety, meaning actions from one thread don't interfere with actions on another thread.
  2. Atomicity, meaning all actions are performed as a single operation (eg. passing a lambda with several operations into a compute method is guaranteed to be performed as one operation, performed before or after another operation and not at the same time)

By throwing a ConcurrentModificationException on modification of a ConcurrentMap while iterating, you've broken the first contract. Broken Java contracts are why I have trust issues.

All joking aside, it would definitely be appreciated if we were able to modify (or iterate with expired values, in the case of #30 ) without getting unexpected exceptions. It was quite strange seeing a ConcurrentModificationException being thrown from a ConcurrentMap.

I've only glanced at some of the code and errors, but it looks like a lock or map copy may be needed when iterating. Possibly an expired value check before an iterator is given?

@jhalterman jhalterman reopened this Jul 26, 2019
@jhalterman
Copy link
Owner

ExpiringMap doesn't implement the iterator, it obtains it from an underlying data structure, so it doesn't have the opportunity to coordinate writes to the map with iteration. So we'd possibly need to create and control our own iterator.

Happy to review a PR for this.

@egg82
Copy link

egg82 commented Jul 27, 2019

Of course! I'll take a closer look at the codebase and PR if I can get some time.

@bratkartoffel
Copy link
Contributor

Woah, sorry for the push spam, didn't expect github to write every single one here...

@jhalterman
Copy link
Owner

This has been fixed in 0.5.11.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants