Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 与Clojure的线程同步_Multithreading_Clojure_Clojure Java Interop - Fatal编程技术网

Multithreading 与Clojure的线程同步

Multithreading 与Clojure的线程同步,multithreading,clojure,clojure-java-interop,Multithreading,Clojure,Clojure Java Interop,我做了一个练习: 按从1到100的顺序打印所有正整数 使用块、信号量或其他类似机制(但避免睡眠),协调两个线程,使两个线程的组合输出以数字顺序显示 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’ 这个练习是针对Ru

我做了一个练习:

  • 按从1到100的顺序打印所有正整数

  • 使用块、信号量或其他类似机制(但避免睡眠),协调两个线程,使两个线程的组合输出以数字顺序显示

     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的,但我想向我的同学们展示Clojure可能是一个很好的任务选择

我没有任何使用任何语言的线程的经验,但我正在考虑使用类似于:

 (def thread_1 (future (swap! my-atom inc) ))
 (def thread_2 (future (swap! my-atom inc) ))
但是@thread_1总是返回相同的值。有没有办法协调Clojure中的两个线程


我在Java中使用ReentrantLock和Condition发现了这一点,现在我正在尝试将其转换为Clojure。

首先,您看到奇怪结果的原因是您取消了对未来的引用,而不是保留数字的原子。未来将返回
交换的结果取消引用时

其次,您可以使用
锁定
(基本上是Java的
同步
)一次只允许增加一个线程并打印:

(def n-atom (atom 0))

(defn action []
  ; Arbitrarily chose the atom to lock on.
  ; It would probably be better to create a private object that can't be otherwise used.
  (locking n-atom
    (println
      (swap! n-atom inc))))

(defn go []
  ; Have each thread do action twice for a total of four times
  (future (doall (repeatedly 2 action)))
  (future (doall (repeatedly 2 action))))

(go)
1
2
3
4
不过我要注意的是,这里确实不应该使用
future
future
用于异步计算结果。它会吞噬错误,直到它被解除引用,因此如果您从未
@
,您将永远不会看到
未来
中出现的异常。最好使用线程池,或者在宏的帮助下,自己启动两个线程以便于使用:

(defmacro thread
  "Starts the body in a new thread."
  [& body]
  `(doto (Thread. ^Runnable (fn [] ~@body))
         (.start)))

(defn go []
  (thread (doall (repeatedly 2 action)))
  (thread (doall (repeatedly 2 action))))

下面是一种使用以下命令协调在同一状态下运行的多个线程的方法:


如果线程的顺序确实重要,并且如果您对非经典线程通信感到好奇,那么可以使用
clojure.core.async
并使用“通道”

这里的一个问题是go例程是在线程池中执行的,因此它们不是专用线程,如果您想使用真正的线程,您应该这样做:

(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))))))))
(需要“[clojure.core.async:作为])
(让[chan one(a/chan 1)
第二条(a/chan 1)]
(a/>!!chan one 1)
(doseq[[thread in out][[1”chan一chan二]
[“两”灿二灿一]]
(a/线程
(循环[]
(出租时[n(a/n 10)
(do(a/close!in)
(a/关闭!关闭)
(do(prn(线程%s中的格式:编号为“%s”线程n))
(a/>!!out(inc n))
(重复(()(())(())))

顺序重要吗?我的意思是线程应该一个接一个地工作,就像你的例子一样。@fl00r,是的,顺序必须是顺序的。这里的信息没有错,但是…使用验证器进行普通终止?让未来在普通终止时崩溃?好吧,这个例子可以改进。@glts公平点!请参阅更新的答案如果你能想到其他的改进,请告诉我。
(def my-agent (agent (range 1 101)))
(while (seq @my-agent)
  (send
    my-agent
    (fn [[n & ns]]
      (when n
        (println "In thread" (.getName (Thread/currentThread))
                 "the number is:" n)
        ns))))
(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`"
(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))))))))