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更糟糕!马上.去产生并返回一个额外的渠道,你可以把它的身体的结果.这可以让您等待完成执行,您无需在示例中执行(针对异步操作).

相关文章

HashMap是Java中最常用的集合类框架,也是Java语言中非常典型...
在EffectiveJava中的第 36条中建议 用 EnumSet 替代位字段,...
介绍 注解是JDK1.5版本开始引入的一个特性,用于对代码进行说...
介绍 LinkedList同时实现了List接口和Deque接口,也就是说它...
介绍 TreeSet和TreeMap在Java里有着相同的实现,前者仅仅是对...
HashMap为什么线程不安全 put的不安全 由于多线程对HashMap进...