Goroutines vs asyncio任务+用于CPU绑定调用的线程池

时间:2017-05-30 22:34:34

标签: python-3.x go concurrency python-asyncio coroutine

goroutines大致相当于python的asyncio任务,还有一个额外的功能,即任何CPU绑定的任务都被路由到ThreadPoolExecutor而不是被添加到事件循环中(当然,假设我们使用没有GIL的python解释器?

我失踪的两种方法之间是否存在实质性差异?当然,除了并发性是Go的一个组成部分所带来的效率和代码清晰度之外。

2 个答案:

答案 0 :(得分:6)

我想我知道答案的一部分。我试图总结一下我对asyncio任务和goroutines之间差异的理解:

1)与asyncio不同,人们很少需要担心他们的goroutine会长时间阻挡。 OTOH,跨goroutine的内存共享类似于跨线程而不是asyncio任务的内存共享,因为goroutine执行顺序保证要弱得多(即使硬件只有一个内核)。

asyncio只会在显式awaityield和某些事件循环方法上切换上下文,而Go运行时可能会打开更微妙的触发器(例如某些函数调用)。所以asyncio是完全合作的,而goroutines主要是合作的(路线图表明它们随着时间的推移会变得更不合作)。

一个非常紧凑的循环(例如使用数值计算)仍然可以阻止Go运行时(嗯,它正在运行的线程)。如果它发生了,它将比在python中产生更小的影响 - 除非它发生在多个线程中。

2)Goroutines对并行计算有现成的支持,这需要在asyncio下采用更复杂的方法。

Go运行时可以并行运行线程(如果有多个核可用),所以它有点类似于在无GIL的python运行时下的线程池中运行多个asyncio事件循环,具有语言感知功能负载平衡器在前面。

3)Go运行时将自动处理单独线程中的阻塞系统调用;这需要在asyncio下明确完成(例如,使用run_in_executor)。

也就是说,就内存成本而言,goroutine非常类似于asyncio任务而不是线程。

答案 1 :(得分:1)

我想你可以认为它在这下面工作,当然。它不是很准确,但足够接近。

但是有一个很大的区别:在Go中你可以编写直线代码,并且所有的I / O阻塞都会自动为你处理。您可以用简单的直线代码调用Read,然后Write,然后调用Read。使用Python asyncio,据我所知,你需要排队一个函数来处理读取,而不是只调用Read。