朱莉娅:了解任务切换何时发生

Kal*_*evi 7 asynchronous julia

我找不到关于@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
Run Code Online (Sandbox Code Playgroud)

此代码生成以下输出

BA
BA
BA
...
Run Code Online (Sandbox Code Playgroud)

我很不清楚@async在上面的代码中由宏创建的任务内部发生任务切换的位置.

如何查看代码中发生任务切换的点?

use*_*730 5

任务切换发生在调用内部println("A"),在某些时候调用write(STDOUT, "A".data).因为isa(STDOUT, Base.AsyncStream)并且没有更专业的方法,这解决了:

write{T}(s::AsyncStream,a::Array{T}) at stream.jl:782
Run Code Online (Sandbox Code Playgroud)

如果你看一下这个方法,你会注意到它调用stream_wait(ct)了当前任务ct,而当前任务又会调用wait().

(另请注意,这println不是原子的,因为wait在写入参数和换行符之间存在潜在可能性.)

你当然可以通过查看所涉及的所有代码来确定何时发生类似的事情.但我不明白为什么你需要确切地知道这一点,因为在使用并行性时,你不应该依赖于切换上下文的进程.如果依赖于某个执行顺序,请明确同步.

(你已经在你的问题中注意到了这一点,但是让我在这里重申一下:根据经验,当使用绿色线程时,你可以在进行IO时期望潜在的上下文切换,因为阻止IO是教科书为什么是绿色的例子线程首先是有用的.)