Thank you very much! I suspected that I using the agents in wrong way. I ran your code and it worked great.
Also I little changed your example to a worker keep only the last task and run it on very large number of tasks (I had problem only on huge collections): (def tasks (ref (into [] (range 1 10000000)))) (defn get-task [tasks] (dosync (let [task (first @tasks)] (alter tasks rest) task))) (defn worker-loop [] (loop [last-task nil] (if-let [task (get-task tasks)] (recur task) last-task))) (defn create-workers [n & options] (vec (repeatedly n (fn [] (future (worker-loop)))))) (def workers (create-workers 100)) (apply max (map deref workers)) This code worked as expected and returned 9999999. But when I replace (def tasks (ref (into [] (range 1 10000000)))) to (def tasks (ref (range 1 10000000))) the problem arose again and this code returnined 1734656. So I think the problem is the lazy collection in the ref. вторник, 23 августа 2016 г., 20:32:37 UTC+7 пользователь adrian...@mail.yu.edu написал: > > Here is working example code demonstrating how you might do this without > agents: > > (in-ns 'user) > > (def tasks (ref (into clojure.lang.PersistentQueue/EMPTY (range 1 1000)))) > > (defn get-task > [tasks] > (dosync > (let [task (first @tasks)] > (alter tasks pop) > task))) > > (defn worker-loop > [] > (loop [completed-tasks []] > (if-let [task (get-task tasks)] > (recur (conj completed-tasks task)) > completed-tasks))) > > (defn create-workers > [n & options] > (vec (repeatedly n (fn [] > (future > (worker-loop)))))) > > (def workers > (create-workers 100)) > > (defn worker-test > [xs] > (= (set (mapcat deref workers)) > (set xs))) > > (worker-test (range 1 1000)) > > On Tuesday, August 23, 2016 at 9:09:31 AM UTC-4, adrian...@mail.yu.edu > wrote: >> >> I haven't run your code yet, but it's bad form to use Clojure's reference >> types inside other reference types. They should store persistent data >> structures to really make any sense in a concurrent context. >> >> On Tuesday, August 23, 2016 at 8:22:00 AM UTC-4, Sergei Koledov wrote: >>> >>> Hello, >>> >>> I had a problem when I run the following code: >>> >>> (defn get-task [tasks] >>> (dosync >>> (let [task (first @tasks)] >>> (alter tasks rest) >>> task))) >>> >>> (defn worker [& {:keys [tasks]}] >>> (agent {:tasks tasks})) >>> >>> (defn worker-loop [{:keys [tasks] :as state}] >>> (loop [last-task nil] >>> (if-let [task (get-task tasks)] >>> (recur task) >>> (locking :out (println "Last task: " last-task)))) >>> state) >>> >>> (defn create-workers [count & options] >>> (->> (range 0 count) >>> (map (fn [_] (apply worker options))) >>> (into []))) >>> >>> (defn start-workers [workers] >>> (doseq [worker workers] (send-off worker worker-loop))) >>> >>> (def tasks (ref (range 1 10000000))) >>> >>> (def workers (create-workers 100 :tasks tasks)) >>> >>> (start-workers workers) >>> (apply await workers) >>> >>> Description: I have several agents (100 in my case). Each agent running >>> in a separate thread. All agents share the one ref with the collection of >>> tasks (range of longs in my case). Each agent get tasks from the collection >>> (in transaction) one by one until the collection becomes empty and then >>> prints the last task which it handle. However, when I run this code it >>> looks like the collection of tasks suddenly becomes empty and workers >>> handle only portion of all tasks (average 25-40% of all number). >>> >>> This code behave as I expected, when I create only one agent or use >>> explicit locking in get-task function: >>> >>> (defn get-task [tasks] >>> (locking :lock >>> (dosync >>> (let [task (first @tasks)] >>> (alter tasks rest) >>> task)))) >>> >>> I run this code on the Clojure 1.8.0 >>> java version "1.8.0_91" >>> Java(TM) SE Runtime Environment (build 1.8.0_91-b14) >>> Java HotSpot(TM) 64-Bit Server VM (build 25.91-b14, mixed mode) >>> >>> Can anyone tell me, what am I doing wrong, or it really looks like a bug >>> in the clojure STM? >>> I already asked this question on stackoverflow.com ( >>> http://stackoverflow.com/questions/39054911/strange-behavior-of-clojure-ref), >>> >>> but so far nobody has been able to help me. >>> >>> P.S. Sorry for my english skill. >>> >> -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.