Clojure core.async 放!对块

Clojure core.async put! versus go block

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

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

我正在努力理解 put 的内部机制!去。我的理解是:

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

我不明白:

  1. 怎么放!实现异步?它也使用线程池吗?
  2. 确实放!也使用停车位?
  3. 有限状态机在 go 块中的作用是什么?是什么让停车成为可能?
  4. 我应该总是尝试使用 put!而不是去,因为它更便宜?那样的话,是不是意味着put!实现与 go 完全相同的并发优势,而 go 仅在我想推理复杂的异步代码时使用?

非常感谢您解开这些谜团。

如果您想了解 core.async 通道的工作原理,没有比 Rich Hickey 的 EuroClojure 2014 演示文稿更好的来源了:Implementation details of core.async channels.

关于您的具体问题:

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

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

  2. "Parking",在 go 块的上下文中,指的是通过记录其当前状态的某些细节来暂停执行 go 块的状态机,并且将它们保存在一个通道或多个通道中,以便以后可以重新启动。 (请注意,这种安排意味着如果所有持有对挂起 go 块的引用的通道都被 GC'd,则 go 块本身也可以被 GC'd。)在其他上下文中它类似地指代将控制线程置于假死状态。 put! 只是一个函数(好吧,它由协议方法支持,但是 that 只是一个协议方法),所以这个概念不适用。

  3. 是的。它基本上遍历 go 块中的代码,可能会在控制达到某个 "custom terminals" 时暂停它(<!>!alt!)。

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