【问题标题】:Clojure core.async put! versus go blockClojure core.async 放!与去块
【发布时间】:2016-02-11 14:16:18
【问题描述】:

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

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

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

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

我不明白:

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

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

【问题讨论】:

    标签: clojure core.async


    【解决方案1】:

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

    至于你的具体问题:

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

      如果 (1) 未立即接受 put 或 (2) 显式 false 作为 put! 调用的最终参数传入(此参数称为 @ 987654327@,详见put!的文档字符串)。

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

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

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

    【讨论】:

    • 神奇的答案米哈尔!我刚刚看完 EuroClojure 上的演示文稿,这很有启发性。感谢您指出这一点。
    • 希望看到一些并排使用各种端口语义的用例,以了解何时使用哪个:)
    猜你喜欢
    • 2016-08-25
    • 2015-07-11
    • 1970-01-01
    • 1970-01-01
    • 2019-07-23
    • 1970-01-01
    • 2019-02-13
    • 2014-02-19
    • 1970-01-01
    相关资源
    最近更新 更多