请考虑以下代码段:
(let [chs (repeatedly 10 chan)] (doseq [c chs] (>!! c "hello")) (doseq [c chs] (println (<!! c))))
执行此操作将永久挂起.这是为什么?
如果我做(去(>!c“你好”)),它的工作很好.
解决方法
要进行异步放置,请使用clojure.core.async / put!
(let [chs (repeatedly 10 chan)] (doseq [c chs] (put! c "hello")) (doseq [c chs] (println (<!! c))))
这个例子在这个例子中是< !!由于所有必要的投注异步发生,总是会阻止.请注意以下事项:
>阻塞作为不同进程之间的同步约束
>> !!和< !!阻塞主线程. go程序在主线程上运行,但是它们的代码通过宏扩展进行修改,以便执行控制被反转,并且可以通过core.async通道阻塞/缓冲逻辑的规律连续排序执行.这种技术通常被称为IOC(控制反转)状态机.
> ClojureScript只有一个线程.因此,它的core.async的实现甚至不包含> !! /< !!.如果您编写旨在与ClojureScript兼容的代码,则只能从go-routines中的通道或从传递给更高级别函数的派生值中取出!并且总是放在go-routine中或使用put!
是(go(>!ch v))等同于(put!ch v)?
是的,但不一样.放!是一个API包装器,围绕channel.async.impl.protocols / WritePort放置的通道实现!方法. (go(>!ch v))的宏扩展最终在同一个方法调用中发生,但将其包装在许多生成的状态机器代码中,以便可能停止放置操作并暂停执行go程序,直到消费者准备就绪从ch(尝试(宏展开`(go(>!ch v)))自己).产生一个去块只做一个异步放置操作是一种浪费,比调用put更糟糕!马上.去产生并返回一个额外的渠道,你可以把它的身体的结果.这可以让您等待完成执行,您无需在示例中执行(针对异步操作).