什么时候Clojure core.async go-blocks有用吗?

时间:2017-06-09 04:09:20

标签: concurrency clojure

由于运行go-blocks的线程池相当小,似乎不推荐使用go-blocks中的某些操作。例如,执行blocking I/O is bad,执行计算繁重的操作是不好的。在go-blocks中运行的一些这样的操作将占用整个线程池,并且根本没有其他的go-blocks能够运行。

Clojure程序员使用go-blocks最常见的场景是什么?它是否主要用于处理已经异步的库?将回调 - 使用库/代码转换为更可口的通道变体?我非常有兴趣看到一些实际的例子,其中带有停车通道操作的go-blocks优于线程。

2 个答案:

答案 0 :(得分:4)

每个线程需要最少量的内存(default 1MB on 64-bit linux)用于其堆栈等。虽然数百个线程在普通计算机上可能不是问题,但是数千个或更多线程可能消耗大量内存(即1000个线程=> 1GB内存)。而且,即使线程被阻塞(未运行),这些资源也会消耗掉。

假设您的任务仅在1-10%的时间内运行。然后使用常规线程消耗的资源比所需资源多10x-100x。由于go块通过" parking"共享线程,因此可以减少10x-100x所需的线程资源。这是好处。

第二个好处是core.async可以在ClojureScript中使用并在浏览器中运行。由于JavaScript(CLJS编译成)只有一个线程,core.async允许人们在浏览器中产生多线程的错觉,即使常规Java线程不可用。

答案 1 :(得分:2)

简而言之,在异步clojure应用程序中使用go个通道时,请使用core.async块。

core.aysnc为您提供内置背压,即一种机制,上面写着“不,我不会因为我们已经很忙而创建新工人”(即创建100000 go块不要破坏你的系统,但不要在家里用线程或带有无界队列的线程池来尝试这个。这是一个很大的胜利,并且无需同步线程来自己完成。需要背压的问题(例如生产者 - 消费者问题)通常很适合这个模型,而core.async是一个很好的选择。

但是,go宏不是clojure核心库的一部分,并不打算用作实现并发的通用工具。其目的是在异步代码之上提供抽象,使其以更加同步的方式流动。考虑一下你的用例,如果模型适合,那就去吧!