是否可以使用经典的Java同步来组合Clojure中的瞬态和缩减器?

时间:2014-04-04 04:01:06

标签: java concurrency clojure

优化我们对标准Clojure 频率功能

的实施
(defn my_frequencies_1 [coll]
  (reduce (fn [counts x]
            (assoc counts x (inc (get counts x 0))))
          {} coll))

我们可以使用瞬变

(defn my_frequencies_2 [coll]
  (persistent!
    (reduce (fn [counts x]
              (assoc! counts x (inc (get counts x 0))))
            (transient {}) coll)))

或者减速器。

(defn my_frequencies_3 [coll]
  (r/fold
    (fn combinef
      ([] {})
      ([coll1 coll2] (merge-with + coll1 coll2)))
    (fn reducef [coll x]
      (assoc coll x (inc (get coll x 0))))
  coll))

但是如果我们尝试使用两种机制

(defn my_frequencies_4 [coll]
  (persistent!
    (r/fold
      (fn combinef
        ([] (transient {}))
        ([coll1 coll2] (transient
                         (merge-with
                           +
                           (persistent! coll1)
                           (persistent! coll2)))))
      (fn reducef [coll x]
        (assoc! coll x (inc (get coll x 0))))
      coll)))

(with-out-str (time (do (my_frequencies_4 data) nil)))

我们遇到了问题。

java.lang.IllegalAccessError: null
              (Unknown Source) sun.reflect.GeneratedConstructorAccessor2.newInstance
              (Unknown Source) sun.reflect.DelegatingConstructorAccessorImpl.newInstance
              (Unknown Source) java.lang.reflect.Constructor.newInstance
              (Unknown Source) java.util.concurrent.ForkJoinTask.getThrowableException
              (Unknown Source) java.util.concurrent.ForkJoinTask.reportResult
              (Unknown Source) java.util.concurrent.ForkJoinTask.join
              (Unknown Source) java.util.concurrent.ForkJoinPool.invoke
               reducers.clj:49 clojure.core.reducers/fjinvoke
              reducers.clj:336 clojure.core.reducers/foldvec
              reducers.clj:357 clojure.core.reducers/eval10225[fn]
               reducers.clj:81 clojure.core.reducers/eval10096[fn]
               reducers.clj:98 clojure.core.reducers/fold
               reducers.clj:96 clojure.core.reducers/fold
    M:\clojure\reducers.clj:63 user/my-frequencies-4
    M:\clojure\reducers.clj:79 user/eval10803

我认为这是因为当时只有一个线程有权处理可变数据结构,即瞬态映射。是否有可能在最后的Clojure代码中使用经典的Java同步原语来规避这个问题?

0 个答案:

没有答案