Skip to content

@sync (@spawn @spawn f(); @spawn @spawn g()) is not thread-safe? #34666

Closed
@tkf

Description

@tkf

@sync @spawn @spawn f() expands roughly to

let sync = Any[]
    task1 = Task() do
        task2 = Task() do
            f()
        end
        task2.sticky = false
        push!(sync, task2)
        schedule(task2)
        task2
    end
    task1.sticky = false
    push!(sync, task1)
    schedule(task1)
    task1
end

This code itself is OK. However, I don't think the following code is thread-safe:

@sync begin
    @spawn @spawn f()
    @spawn @spawn g()
end

This is because push!(sync, task2) for @spawn f() and @spawn g() can be executed in parallel. This came up in #34543 (comment)

How should it be fixed? Maybe expand @spawn ... to something like below?

if $(Expr(:islocal, :sync))
    local sync_sub = Any[]
    task = Task() do
        local sync = sync_sub
        ...
    end
else
    task = Task() do
        ...
    end
end
task.sticky = false

if $(Expr(:islocal, :sync))
    push!(sync, task)
    @async begin
        wait(task)
        append!(sync, sync_sub)  # merge sub-tasks
    end
end

schedule(task)

Metadata

Metadata

Assignees

Labels

multithreadingBase.Threads and related functionality

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions