Hello world, and Julia behaves strangely

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 :slight_smile:

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.

1 Like