Qestion1:
Because the max size of chnl
is 0, the following code should be blocked. Why the following code is not blocked?
chnl = Channel() do ch
foreach(i -> put!(ch, i), 1:4) # not blocked
end;
The following is blocked.
chnl = Channel()
foreach(i -> put!(ch, i), 1:4) # blocked here
Question 2:
The following result is not as expected.
function take_channel(c)
d = take!(c)
println("get data: ", d)
p()
end
function p()
println("I am here")
end
c = Channel{Int64}(0)
@async take_channel(c) #
put!(c, 1)
@async take_channel(c)
put!(c, 2)
The output is
get data: 1 #why `get data 2` is not printed, and no `I am here`
Testing LDTSimulate tests passed
If I put the code in @testset
the result looks as expected,
function take_channel(c)
d = take!(c)
println("get data: ", d)
p()
end
function p()
println("I am here")
end
@testset "test channel" begin
c = Channel{Int64}(0)
@async take_channel(c) #
put!(c, 1)
@async take_channel(c)
put!(c, 2)
end
The results are as expected.
get data: 1
Test Summary: |I am here
get data: 2
I am here
test channel | No tests
Testing LDTSimulate tests passed
chnl = Channel() do ch
foreach(i -> put!(ch, i), 1:4)
end
The inner function is blocked, but it’s scheduled asynchronously, so it doesn’t block the main thread. Basically that is similar to doing:
chnl = Channel()
@async foreach(i -> put!(ch, i), 1:4)
Issue 2 is has to do with scheduling and REPL. I believe if you do:
@sync begin
c = Channel{Int64}(0)
@async take_channel(c) #
put!(c, 1)
end
The @sync
will cause the execution to pause and allow the @async task to finish. My guess is that the println() is giving up control which allows the REPL to execute again. You might also be able to do a sleep(1)
after you do the put!(c, 1)
which should give the async task time to finish.
2 Likes
note the Channel()
constructor which is similar to Channel(0)
creates an unbuffered channel i.e put!
blocks until a matching take!
is called. And vice-versa.
For me the question 2 works just fine.
function take_channel(c)
d = take!(c)
println("get data: ", d)
p()
end
function p()
println("I am here")
end
c = Channel{Int64}(0)
@async take_channel(c) #
put!(c, 1);
@async take_channel(c)
put!(c, 2);
And i get the expected output.
Thank you so much for your answer. The code you suggested works as expected. I am surprised that the default REPL does not run as @sync
. But it also does not run as @async. There should be some different behaviour not described in the document.
@sync begin
c = Channel{Int64}(0)
@async take_channel(c) #
put!(c, 1)
end
I found a very clear explanation, much clearer than the document. Hope it could help other users.
When to use @sync and @async