Clojure – 为什么在阻塞插入到频道时执行挂起? (core.async)

前端之家收集整理的这篇文章主要介绍了Clojure – 为什么在阻塞插入到频道时执行挂起? (core.async)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
请考虑以下代码段:
(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更糟糕!马上.去产生并返回一个额外的渠道,你可以把它的身体的结果.这可以让您等待完成执行,您无需在示例中执行(针对异步操作).

猜你在找的Java相关文章