liveBook · Manning

ConcurrentHashMap

As explained in Clojure: The Essential Reference

java.util.concurrent.ConcurrentHashMap is a Java hash table supporting concurrent access and updates by multiple threads.

`ConcurrentHashMap` is a Java map that supports updates from multiple threads. That makes it a candidate for parallel Clojure reductions, but thread safety alone does not make it usable with `clojure.core.reducers/fold`. A direct fold raises an `IllegalArgumentException` because the required key-value reduction protocol is missing. section 7.1.1

Extending `IKVReduce` lets the map participate in a fold, but the shown implementation reduces sequentially. To use parallel fold, extend `r/CollFold` instead: collect the map’s keys into a vector, then fold that vector while updating the concurrent map. section 7.1.1

(defn foldmap [m n combinef reducef]      ; #1
  (#'r/foldvec
    (into [] (keys m))
    n
    combinef
    reducef))

(extend-protocol r/CollFold               ; #2
  java.util.concurrent.ConcurrentHashMap
  (coll-fold
    [m n combinef reducef]
    (foldmap m n combinef reducef)))

(def a-large-map (ConcurrentHashMap. (large-map 100000 100)))

(time                                     ; #3
  (dorun
    (into {}
      (r/fold
        (combinef a-large-map)
        reducef
        a-large-map))))
"Elapsed time: 430.96208 msecs"

The `CollFold` extension delegates to a vector fold over the map’s keys; the example reports about 431 ms for its workload. section 7.1.1

The practical distinction is between a collection that tolerates concurrent updates and one that `fold` knows how to partition. Unsupported mutable Java collections, such as `HashMap`, should not be treated as safe substitutes. section 7.1.1

How Clojure: The Essential Reference covers it

How deep it goes
Works through a failed fold, a sequential protocol extension, and a parallel extension; stops short of Java hash-table internals.
Examples
Compares protocol extensions while updating map values with a pi approximation and reporting elapsed times.
What it assumes
Assumes familiarity with Clojure reducers and Java interop while showing the protocol extensions needed for folding.
What you can do after
Apply it via Clojure reducers by extending CollFold for a parallel fold over its keys.
How it connects
Connects ConcurrentHashMap to reducers, IKVReduce, CollFold, and parallel reduction.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Clojure: The Essential Reference. The section links point to the parts of the book it draws on.