Avoiding Race Condition using Channels

The race condition is because the main thread might call println(acc[]) “at the same time” the asynchronous task is updating it.

Apart from the printing in the end, yes, this is correct. Channels are introduced in the manual as a way to synchronize asynchronous tasks, but they are thread-safe and can also be used in a multi-threads context.

Note that, as said above, you need some way to know when the computation is finished. Channels can help with that as well, especially if you can close them once the computation is finished. Your initial example could for example look like this:

using Base.Threads
Threads.nthreads()

chnl = Channel{Int}(Threads.nthreads())

task = @async let acc = 0  # acc is now a local variable; nobody else will access it
    for i in chnl          # iteration will stop when the channel is closed
        acc += i
    end
    acc                    # the task returns the final value of the accumulator
end
# or even, in this specific case:
# task = @async sum(chnl)


@threads for _ in 1:10000
  put!(chnl, 1)
end

close(chnl)  # close the channel once the computation is finished
fetch(task)  # wait for the task to finish and get its return value