On 25.05.14 17:45, Phil Steitz wrote:
> On 5/25/14, 8:18 AM, Romain Manni-Bucau wrote:
>>> And please consider reacting to Phils comment on the removal of
>>> synchronized keywords. It took years to pinpoint the race issues in the
>>> JCS code. I don't claim the current situation to be perfect but at least
>>> it does not cause data corruption. I want to go forward, not backward.
> 
> On this topic, one thing that would probably be helpful would be if
> someone familiar with the code could comment a little or post
> references to past bugs that show what race conditions / data
> invariants we have to worry about.  If there is a locking strategy
> implicit in the pre-CHM code, it would be great to make that
> explicit so Romain can know what he has to worry about beyond just
> maintaining integrity of the backing store (which CHM can do).

JCS implements a composite cache, that is, a cache with a memory cache
with different eviction algorithms (you may call it level one) and zero
or more "auxiliaries" that handle the second level of caching: disks,
databases, distributed caches etc.

We have two issues with synchronization here. One is more or less some
kind of a transaction issue that means that data operations on the *same
cache key* should be performed in sequence and completed through the
chain of auxiliaries. That's why CompositeCache is synchronized. See
JCS-73. I tried several approaches to get rid of this synchronization
but everything I came up with was slower than the synced code.

The other issue is the handling of common data structures within the
cache implementations. For example putting a value into the LRU memory
cache requires not only putting it into the map but updating the linked
list that keeps track on the LRU element. So having a CHM doesn't help
much here.

The same is true for most of the auxiliaries where several data
structures have to be kept consistent. The only exception are the two
disk caches where I managed to get the synchronization out of the code
with the help of NIO. See JCS-69, JCS-76, JCS-82, JCS-92 to name just a few.

In addition, JCS employs several background threads to queue operations
and to do eviction. If you want to see the effect of unsynchronized
access, have a look at the cache statistics. In continuous operation,
the numbers are plain nonsense.

That said: Quite a few of Romains replacements with CHM are maps that
keep track of certain auxiliary caches of the same type within their
managers. They employ the simple pattern

cache = map.get(cacheName);
if (cache == null)
{
  // create cache instance, open databases, start servers, create files
etc etc.
}

So if you want to avoid to run these expensive operations, you don't
want to create a cache instance on spec just for putIfAbsent() and you
need synchronization again. That is at least my level of knowledge.
(I don't like this construct of multiple managers and factories, I
consider it over-engineered but it is not high on my list)

Hope I could shed some light on this.
Bye, Thomas.

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org
For additional commands, e-mail: dev-h...@commons.apache.org

Reply via email to