• Bug
  • Status: Closed
  • 2 Major
  • Resolution: Fixed
  • ehcache-core
  • jhouse
  • Reporter: mads1980
  • February 03, 2011
  • 0
  • Watchers: 3
  • July 27, 2012
  • July 26, 2011

Description

Race conditions occur when threads on different nodes try putIfAbsent at the same time, resulting in that both puts() succeed (the last one wins out), even though the second one (whichever of the two it is) should fail.

I am quite familiar with EhCache’s internals, so I know this is due to the way that changes (puts, removes, updates, etc.) are propagated - the RMI (both sync and async) replicators are implemented as listeners, and all relevant methods in CacheListener return , so there's no synchronous mechanism (or cluster-wide locking for that matter) to know whether the put in another node would succeed or not.

I’m not sure whether this can even be done with the current infrastructure. Probably pairing EhCache with Terracotta would be a better alternative for scenarios that require sensitive locking.

However, it is confusing to call Ehcache.putIfAbsent() without the expected behavior. At least this should be documented.

Comments

Manuel Dominguez Sarmiento 2011-02-03

This is not exclusive to putIfAbsent, the other ConcurrentMap-like methods - for instance, replace(Element, Element) suffer the same kind of problem.

gluck 2011-02-03

Yes, none of the CAS operations guarantee this for replicated caching, only for standalone and Terracotta Server Array distributed caches.

We should throw a CacheException when these methods are called on a cache configured for RMI, JGroups and JMS replication.

James House 2011-07-26

putIfAbsent(Element), replace(Element), replace(Element, Element) and removeElement(Element) now throw exceptions when non-supporting replication (RMI, JMS, JGroups) is configured.