我有一个练习:
按顺序打印从 1 到 100 的所有正整数。
使用 block 、信号量或其他类似机制(但避免休眠)协调两个线程,使两个线程的组合输出按数字顺序显示。
Sample Output In thread one: The number is ‘1’ In thread two: The number is ‘2’ In thread one: The number is ‘3’ In thread two: The number is ‘4’
该练习适用于 Ruby,但我想向我的类(class)展示 Clojure 可能是该任务的一个不错的选择。
我对任何语言的线程都没有任何经验,但我想使用类似的东西:
(def thread_1 (future (swap! my-atom inc) ))
(def thread_2 (future (swap! my-atom inc) ))
但 @thread_1 总是返回相同的值。有没有办法在 Clojure 中协调两个线程?
我找到了 example在 Java 中使用 ReentrantLock 和 Condition,现在我正在尝试将其转换为 Clojure。
最佳答案
如果线程的顺序很重要,并且如果您对非经典线程通信感到好奇,您可以使用 clojure.core.async
并使用“ channel ”。
(require '[clojure.core.async :as a])
(let [chan-one (a/chan 1)
chan-two (a/chan 1)]
(a/>!! chan-one 1)
(doseq [[thread in out] [["one" chan-one chan-two]
["two" chan-two chan-one]]]
(a/go-loop []
(when-let [n (a/<! in)]
(if (> n 10)
(do (a/close! in)
(a/close! out))
(do (prn (format "In thread %s: The number is `%s`" thread n))
(a/>! out (inc n))
(recur)))))))
输出是
"In thread one: The number is `1`"
"In thread two: The number is `2`"
"In thread one: The number is `3`"
"In thread two: The number is `4`"
"In thread one: The number is `5`"
"In thread two: The number is `6`"
"In thread one: The number is `7`"
"In thread two: The number is `8`"
"In thread one: The number is `9`"
"In thread two: The number is `10`"
这里有个问题是go-routines在线程池中执行,所以它们不是专用线程,如果你想使用真正的线程,你应该这样:
(require '[clojure.core.async :as a])
(let [chan-one (a/chan 1)
chan-two (a/chan 1)]
(a/>!! chan-one 1)
(doseq [[thread in out] [["one" chan-one chan-two]
["two" chan-two chan-one]]]
(a/thread
(loop []
(when-let [n (a/<!! in)]
(if (> n 10)
(do (a/close! in)
(a/close! out))
(do (prn (format "In thread %s: The number is `%s`" thread n))
(a/>!! out (inc n))
(recur))))))))
关于multithreading - 与 Clojure 的线程同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52302690/