You have a race condition in your output to stdout.
The newline, you don’t expect is from your waiter tasks println command.
The race condition, which produces strange behavior, is that you use stdout io stream in both threads (main+waiter). Additional to your println commands, show is called for the return value of put!.
The channels put! and take! are thread-safe as they call lock/unlock on the channel, but println is not, because the io stream STDOUT, which is typically buffered too, is not synchonized via lock/unlock.
You can have it even more weird, for example, if you supress the show output, by putting a ; at the end of the put! command:
julia> chan = Channel(1)
Channel{Any}(1) (empty)
julia> waiter = @task begin
while true
wait(chan)
msg = take!(chan)
println("got ",msg)
if msg == "stop" break end
end
end
Task (runnable) @0x000000000b7d2e90
julia> schedule(waiter)
Task (runnable) @0x000000000b7d2e90
julia> put!(chan, "xxxxx");
got
julia>
The output of println("got ",msg) is at some time point disrupted by clearing STDOUT, so only "got " made it through. But if you change
println("got ",msg)
to
println("got "*msg)
the output gets through:
julia> chan = Channel(1)
Channel{Any}(1) (empty)
julia> waiter = @task begin
while true
wait(chan)
msg = take!(chan)
println("got "*msg)
if msg == "stop" break end
end
end
Task (runnable) @0x000000000b202e90
julia> schedule(waiter)
Task (runnable) @0x000000000b202e90
julia> put!(chan, "xxxxx");
got xxxxx
julia>
because the complete output string is composed before writing to STDOUT and writing to STDOUT is done once by println. But beware, using string concatenation before calling println is NOT the general solution here, because it depends on the buffer size of STDOUT. If several threads needs to write to STDOUT you have to synchronize it on your own.
If you change your original code from
println("got ", msg)
to
print("got "*msg*"\n")
you probably wouldn’t have started this thread ![]()
julia> chan = Channel(1)
Channel{Any}(1) (empty)
julia> waiter = @task begin
while true
wait(chan)
msg = take!(chan)
print("got "*msg*"\n")
if msg == "stop" break end
end
end
Task (runnable) @0x000000000b242e90
julia> schedule(waiter)
Task (runnable) @0x000000000b242e90
julia> put!(chan, "message")
got message
"message"
All looks good, but it is only because buffer size is large enough for these short examples.
So, you are messing with stdout in a non thread-safe way and that produces weird outputs.