Search code examples
javaconcurrencyconcurrenthashmap

ConcurrentHashMap with complicated objects


I've taken some concurrent LRU cache implementation from the web, they have there HashMap and synchronized blocks. What I want is to use ConcurrentHashMap and avoid (where posible) using synchronized blocks. I've put ConcurrentHashMap instead of HashMap and everything went wrong. Thread exits on map.get(key). Maybe my parameters of ConcurrentHashMap need to be customized somehow?

        private ConcurrentHashMap<Object, LRUListEntry> map;

        protected class LRUListEntry extends Object
        {
            LRUListEntry next;
            LRUListEntry prev;
            Object value;
            Object key;
            int hits;
            final int penalty = -1;

            public String toString()
            {
                return key + "=" + value;
            }

            public Object getKey()
            {
                return key;
            }

            public Object getValue()
            {
                return value;
            }
        }

Solution

  • The problem is that the prev and next LRU references are modified on every access to reorder the entry as the least recently used. The implementation assumes that these operations are being performed atomically, which is not true if the synchronized blocks are removed. Java's LinkedHashMap is a nice implementation of your snippet, and is provided in the standard library.

    ConcurrentLinkedHashMap provides a concurrent version of the LRU algorithm. The design document describes at a high-level the ideas used. This project was a basis for Guava's Cache, with the modified approach described in this presentation. Both projects have good code level documentation and unit tests if you are interested in the low-level details.