Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[release-1.9] add docs on task migration (#50047) #50054

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions base/threadingconstructs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ export threadid, nthreads, @threads, @spawn,

Get the ID number of the current thread of execution. The master thread has
ID `1`.

!!! note
The thread that a task runs on may change if the task yields, which is known as [`Task Migration`](@ref man-task-migration).
For this reason in most cases it is not safe to use `threadid()` to index into, say, a vector of buffer or stateful objects.

"""
threadid() = Int(ccall(:jl_threadid, Int16, ())+1)

Expand Down Expand Up @@ -208,7 +213,7 @@ For example, the above conditions imply that:
- Write only to locations not shared across iterations (unless a lock or atomic operation is
used).
- The value of [`threadid()`](@ref Threads.threadid) may change even within a single
iteration.
iteration. See [`Task Migration`](@ref man-task-migration)

## Schedulers

Expand Down Expand Up @@ -334,8 +339,10 @@ the _value_ of a variable, isolating the asynchronous code from changes to
the variable's value in the current task.

!!! note
See the manual chapter on [multi-threading](@ref man-multithreading)
for important caveats. See also the chapter on [threadpools](@ref man-threadpools).
The thread that the task runs on may change if the task yields, therefore `threadid()` should not
be treated as constant for a task. See [`Task Migration`](@ref man-task-migration), and the broader
[multi-threading](@ref man-multithreading) manual for further important caveats.
See also the chapter on [threadpools](@ref man-threadpools).

!!! compat "Julia 1.3"
This macro is available as of Julia 1.3.
Expand Down
12 changes: 12 additions & 0 deletions doc/src/manual/multi-threading.md
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,18 @@ threads in Julia:
This may require some transitional work across the ecosystem before threading
can be widely adopted with confidence. See the next section for further details.

## [Task Migration](@id man-task-migration)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this section mention the :static scheduler (not mentioned anywhere) as a way to recover the old behaviour?

Copy link
Sponsor Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense. Let's do that in #48542 given this is a backport


After a task starts running on a certain thread (e.g. via [`@spawn`](@ref Threads.@spawn) or
[`@threads`](@ref Threads.@threads)), it may move to a different thread if the task yields.

This means that [`threadid()`](@ref Threads.threadid) should not be treated as constant within a task, and therefore
should not be used to index into a vector of buffers or stateful objects.

!!! compat "Julia 1.7"
Task migration was introduced in Julia 1.7. Before this tasks always remained on the same thread that they were
started on.

## Safe use of Finalizers

Because finalizers can interrupt any code, they must be very careful in how
Expand Down