Clojure core.async把!与阻止

时间:2016-02-11 14:16:19

标签: clojure core.async

我在这里阅读了关于core.async这篇伟大的文章:

http://www.core-async.info/reference/primitives

我很难理解put的内部机制!去。我理解:

  1. 把!是异步的,可以接受回调。这在简单的场景中效果很好,但你可以以回调地狱结束。
  2. go修复回调地狱,并允许以同步方式编写异步代码。
  3. go利用轻量级线程池,利用停放来实现并发。
  4. go使用有限状态机
  5. 我不明白:

    1. 怎么放!实现异步?它是否也使用线程池?
    2. 放!还用停车?
    3. 有限状态机在go块中的作用是什么?它是什么使停车?
    4. 我应该总是尝试使用put!而不是因为它更便宜?在那种情况下,这是否意味着放!实现与go完全相同的并发性,只有当我想推理复杂的异步代码时才会使用它?
    5. 非常感谢能够揭开这些神秘面纱。

1 个答案:

答案 0 :(得分:8)

如果你想了解core.async频道是如何运作的,那么Rich Hickey的2014年EuroClojure演示文稿就没有更好的资源了:Implementation details of core.async channels

至于你的具体问题:

  1. 如果不立即接受put!,它会在通道内部的队列上放置待处理的放置(要放在通道上的值+ put!回调)。请注意,如果队列中没有空间,则会抛出异常(最大容量当前固定为1024)。

    如果(1)未立即接受put,或者(2)将false作为put!调用的最终参数传入({1}},则将在池化线程上调用回调(此参数名为on-caller?,有关详细信息,请参阅put!的文档字符串。)

  2. go块的上下文中,“停放”是指通过记录其当前状态的某些细节并将其保存在通道内来暂停执行go块的状态机,或者可能是几个通道,以便以后可以重新启动。 (请注意,这种安排意味着如果所有持有对已挂起的go块的引用的通道都是GC,那么go块本身也可以是GC。)在其他情况下,它同样指的是将控制线程置于假死状态。 put!只是一个函数(好吧,它由协议方法支持,但 只是一种协议方法),所以这个概念不适用。

  3. 是。它基本上会逐步执行go块中的代码,当控件到达某些“自定义终端”时可能会暂停它(<!>!alt!)。

  4. 不一定,您应该首先考虑内部队列溢出的风险(见上文第1点)。