I could not find detailed documentation about the @async
macro. From the docs about parallelism I understand that there is only one system thread used inside a Julia process and there is explicit task switching going on by the help of the yieldto
function - correct me if I am wrong about this.
For me it is difficult to understand when exactly these task switches happen just by looking at the code, and knowing when it happens seems crucial.
As I understand a yieldto
somewhere in the code (or in some function called by the code) needs to be there to ensure that the system is not stuck with only one task.
For example when there is a read
operation, inside the read there probably is a wait
call and in the implementation of wait
there probably is a yieldto
call. I thought that without the yieldto
call the code would stuck in one task; however running the following example seems to prove this hypothesis wrong.
@async begin # Task A
while true
println("A")
end
end
while true # Task B
println("B")
end
This code produces the following output
BA
BA
BA
...
It is very unclear to me where the task switching happens inside the task created by the @async
macro in the code above.
How can I tell about looking at some code the points where task switching happens?
The task switch happens inside the call to println("A")
, which at some point calls write(STDOUT, "A".data)
. Because isa(STDOUT, Base.AsyncStream)
and there is no method that is more specialized, this resolves to:
write{T}(s::AsyncStream,a::Array{T}) at stream.jl:782
If you look at this method, you will notice that it calls stream_wait(ct)
on the current task ct
, which in turn calls wait()
.
(Also note that println
is not atomic, because there is a potential wait
between writing the arguments and the newline.)
You could of course determine when stuff like that happens by looking at all the code involved. But I don't see why you would need to know this exactly, because, when working with parallelism, you should not depend on processes not switching context anyway. If you depend on a certain execution order, synchronize explicitly.
(You already kind of noted this in your question, but let me restate it here: As a rule of thumb, when using green threads, you can expect potential context switches when doing IO, because blocking for IO is a textbook example of why green threads are useful in the first place.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With