You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
We experienced situation were the ExpiringMap returned an expired entry after ExpirationListener was already notified that this specific entry was expired.
The map is configured with the policy ExpirationPolicy.ACCESSED (version 0.5.10)
The expired entry is returned in subsequent calls to get(Object) (not only once) until it is not accessed for a certain time again. Then the expired entry is expired again and correctly removed from the map.
I don't know if anybody experienced this issue or at least if this behaviour is a problem in other applications at all.
A little (simplified) background why this was in issue - at least in our application ;-) : In our case we used the map to "cache" some "sequentializers" per "destination" (/key) (owning some kind of Thread). In case that destination is not "used" anymore we want to remove the sequentializer and stop the backed thread (to minimize resources). As soon as there is a task again for that specific destination we create and cache a new sequentializer (which is reused again until it is not needed for a specified time).
For this usecase we used the handy ExpiringMap (great work by the way :-) )
This issue occures under very rare conditions. It seems to be a timing issue between the "application-thread" and the "ExpiringMap-Expirer-Thread" where the application tries to get the object at the exact same time the Expirer wanted to remove it.
I have created a simplified test-case which tries to repoduce this issue (see TestExpiringMap.java below).
In those cases were this issue occures one would see the following sequence of "log-events":
It is easier to reproduce if one modifies the actual ExperingMap and add a Thread.sleep(1); in the get(Object) method
This does not change any consistency locking but just "simulates" unfortunate thread scheduling.
We experienced situation were the ExpiringMap returned an expired entry after ExpirationListener was already notified that this specific entry was expired.
The map is configured with the policy
ExpirationPolicy.ACCESSED
(version 0.5.10)The expired entry is returned in subsequent calls to
get(Object)
(not only once) until it is not accessed for a certain time again. Then the expired entry is expired again and correctly removed from the map.I don't know if anybody experienced this issue or at least if this behaviour is a problem in other applications at all.
A little (simplified) background why this was in issue - at least in our application ;-) : In our case we used the map to "cache" some "sequentializers" per "destination" (/key) (owning some kind of Thread). In case that destination is not "used" anymore we want to remove the sequentializer and stop the backed thread (to minimize resources). As soon as there is a task again for that specific destination we create and cache a new sequentializer (which is reused again until it is not needed for a specified time).
For this usecase we used the handy ExpiringMap (great work by the way :-) )
This issue occures under very rare conditions. It seems to be a timing issue between the "application-thread" and the "ExpiringMap-Expirer-Thread" where the application tries to get the object at the exact same time the Expirer wanted to remove it.
I have created a simplified test-case which tries to repoduce this issue (see
TestExpiringMap.java
below).In those cases were this issue occures one would see the following sequence of "log-events":
It is easier to reproduce if one modifies the actual ExperingMap and add a
Thread.sleep(1);
in theget(Object)
methodThis does not change any consistency locking but just "simulates" unfortunate thread scheduling.
The sequence seems to be:
main
acquires read-lock; getEntry is stored fork1=v1
; releases read-lockExpirer
acquires write-lock; removesk1=v1
; notifies expiration listener; releases write-lockmain
now checks ifExpirationPolicy.ACCESSED
is used, and resets the Entrymain
acquires write-lock;k1=v1
is "reorderd" by removingk1
(which has no effect; was already removed byExpirer
) and re-puts the already expiredv1
.main
gets the already expired valuev1
returned from theget(Object)
method.get(Object)
fork1
will return the expiredv1
until it is expired again.TestExpiringMap.java
The text was updated successfully, but these errors were encountered: