我找不到有关@async
宏的详细文档。从有关并行性的文档中,我了解到Julia进程内仅使用了一个系统线程,并且借助于yieldto
函数进行了显式的任务切换-如果我对此做错了,请纠正我。
对我而言,仅通过查看代码就很难理解这些任务切换的确切时间,并且知道何时发生这些任务至关重要。
据我了解,需要在代码中的某个地方(或代码所调用的某些函数中)添加一个yieldto
,以确保系统不会仅停留在一项任务上。
例如,当有一个read
操作时,在读取内部可能有一个wait
调用,而在wait
的实现中可能有一个yieldto
调用。我以为如果没有yieldto
调用,代码将停留在一项任务中。但是,运行以下示例似乎证明了该假设是错误的。
@async begin # Task A
while true
println("A")
end
end
while true # Task B
println("B")
end
此代码产生以下输出
BA
BA
BA
...
对我来说,目前尚不清楚任务切换发生在上面代码中的
@async
宏创建的任务内。我该如何看待某些代码,以了解发生任务切换的地方?
最佳答案
任务切换发生在对println("A")
的调用内,该调用有时称为write(STDOUT, "A".data)
。因为isa(STDOUT, Base.AsyncStream)
并且没有更专业的方法,所以可以解决:
write{T}(s::AsyncStream,a::Array{T}) at stream.jl:782
如果您查看此方法,您会注意到它在当前任务
stream_wait(ct)
上调用ct
,而该任务又调用wait()
。(还要注意,
println
不是原子的,因为在编写参数和换行符之间存在潜在的wait
。)您当然可以通过查看所有涉及的代码来确定何时发生类似的事情。但是我不明白为什么您需要确切地知道这一点,因为在使用并行性时,您不应该依赖进程,无论如何也不要切换上下文。如果您依赖特定的执行顺序,请进行显式同步。
(您已经在问题中注意到了这一点,但是让我在这里重申一下:根据经验,使用绿色线程时,在执行IO时可以预期潜在的上下文切换,因为阻塞IO是为什么绿色的教科书示例。线程首先很有用。)