The lazy sequence works with the code I provided as well. On Tuesday, August 23, 2016 at 9:29:08 AM UTC-4, Sergei Koledov wrote: > > Yes, you are absolutely right. After i modify the code as you advised, it > worked correctly. Thank you very much! > Does it mean that is necessary to avoid the use of lazy data structures > within the STM? > > вторник, 23 августа 2016 г., 19:57:58 UTC+7 пользователь hitesh написал: >> >> Taking a quick look at this, I *think* the problem crops up in your tasks >> being a lazy sequence. >> >> Modify this >> >> (def tasks (ref (range 1 10000000))) >> >> to this >> >> (def tasks (ref (doall (range 1 10000000)))) >> >> Running that with your large endpoint was taking a lot of time, so I'd >> suggest running it with 1e5 as that will finish much quicker. >> >> >> >> 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.