Why `lock` does NOT work for full channel?

Actually, i think my answer was incorrect; some slight variations recover the same underlying problem, even with a separate lock:

function showme(n, m)
    c = Channel(m)
    l = ReentrantLock()
    t1 = @async begin
        for x in 1:n

            put!(c, 0)
            sleep(0.1)
        end
    end
    t2 = @async begin
        lock(l)
        for x in 1:n
            put!(c,1)
            sleep(0.001)
        end
        unlock(l)
    end

    d= []
    sleep(1)
    for _ in 1:2n
        push!(d, take!(c))
    end
    show(d)
end

julia> showme(5,5)
Any[0, 1, 1, 1, 1, 1, 0, 0, 0, 0]
julia> showme(5,4)
Any[0, 1, 1, 1, 1, 0, 1, 0, 0, 0]

After digging in, it appears that lock(c::Channel) calls lock(c.cond_take.lock), the underlying ReentrantLock for the channel. And, your put! call ends up nesting lock calls (see https://github.com/JuliaLang/julia/blob/master/base/channels.jl, around line 313), and observe also:

julia> c = Channel(4)
Channel{Any}(4) (empty)

julia> islocked(c.cond_put.lock)
false

julia> lock(c)

julia> lock(c)

julia> islocked(c.cond_put.lock)
true

julia> unlock(c)

julia> islocked(c.cond_put.lock)
true

julia> unlock(c)

julia> islocked(c.cond_put.lock)
false

My intuition is that these nested locks (which I don’t quite understand) are interacting with you asynchronous code in unanticipated ways. Perhaps your lock call in t2 is nesting within a lock that is blocking triggered by a put! in t1?

It looks you can lock the calls within t1 to get the behaviour you want:

function showme(n, m)
    c = Channel(m)
    t1 = @async begin
        for _ in 1:n
            lock(c)
            put!(c, 0)
            unlock(c)
            sleep(0.1)
        end
    end
    t2 = @async begin
        lock(c)
        for _ in 1:n
            put!(c,1)
            sleep(0.001)
        end
        unlock(c)
    end

    d= []
    sleep(1)
    for _ in 1:2n
        push!(d, take!(c))
    end
    show(d)
end
julia> showme(5,5)
Any[0, 1, 1, 1, 1, 1, 0, 0, 0, 0]
julia> showme(5,4)
Any[0, 1, 1, 1, 1, 1, 0, 0, 0, 0]