# Julia 1.7 says it can switch the thread your task is on. How often does that happen, and how can it be disabled?

**URL:** <https://discourse.julialang.org/t/julia-1-7-says-it-can-switch-the-thread-your-task-is-on-how-often-does-that-happen-and-how-can-it-be-disabled/75373>\
**Category:** General Usage\
**Tags:** task, threads\
**Created:** [January 28, 2022, 2:54pm UTC](https://discourse.julialang.org/t/julia-1-7-says-it-can-switch-the-thread-your-task-is-on-how-often-does-that-happen-and-how-can-it-be-disabled/75373 "2022-01-28T14:54:14Z")\
**Posts on this page:** 1\
**Showing post:** 4

<div class="post-metadata">

**Author:** ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)\
**Post date:** [January 28, 2022, 3:44pm UTC](https://discourse.julialang.org/t/julia-1-7-says-it-can-switch-the-thread-your-task-is-on-how-often-does-that-happen-and-how-can-it-be-disabled/75373/4 "2022-01-28T15:44:30Z")

</div>

Let’s not confuse threads with tasks here. Primarily, ThreadPinning.jl is for pinning Julia threads to specific cores. That’s it. Whether tasks are started on and/or stay on a certain Julia thread is an entirely different thing.

> [@heyx3](#):
>
> Does this mean that the thread I’m running on can no longer be controlled?

First things first: Julia implements task-based multithreading (somewhat similar to Go), so the general idea is that users care about tasks and not so much about threads. You just `@spawn` whatever you want and let the scheduler put this on a certain thread or, if necessary, let the task migrate to another thread if necessary. In some sense, this is great since it abstracts away some of the more low-level scheduling aspects and also facilitates composable / nested multithreading.  
However, sometimes you want / need to control on which Julia thread (and, if pinned to a core in some way, which core) a task runs on. The good news is, this is still possible (see below). However, I must say that my feeling is that it is not really supported since it might undermine the idea of composable task-based multithreading (personally, I think we should support both!).

So, how can we “pin” a task to a certain Julia thread? The keyword here is `sticky`. If you look at the source code of `@threads` (in particular [this function](https://github.com/JuliaLang/julia/blob/a25f128a8fc38eb86f1067316509838d29c8c007/base/threadingconstructs.jl#L25)), you see that the task(s) corresponding to the body of the multithreaded loop will get [put on specific threads](https://github.com/JuliaLang/julia/blob/a25f128a8fc38eb86f1067316509838d29c8c007/base/threadingconstructs.jl#L32) and, importantly, get the property [`sticky = true`](https://github.com/JuliaLang/julia/blob/a25f128a8fc38eb86f1067316509838d29c8c007/base/threadingconstructs.jl#L31). This means, that the task will stay on this Julia thread and won’t migrate away. So, if you write a loop like

```julia
@threads for i in 1:nthreads()
    f(i)
end

```

you can be sure that `f(i)` will run on the Julia thread `i` and will stay there. Contrast this to `@spawn` which has [`sticky = false`](https://github.com/JuliaLang/julia/blob/a25f128a8fc38eb86f1067316509838d29c8c007/base/threadingconstructs.jl#L183). Hence, tasks spawned in that way can, in principle, migrate between threads.

Now you might say, well that’s great but I sometimes want to “spawn” a single task on a specific thread… While you could use `@threads` for this,

```julia
@threads for i in 1:nthreads()
    if i == thread_that_should_run_the_computation
        f()
    end
end

```

this is arguably overly complex and also somewhat of a misuse of `@threads`. Fortunately, we can essentially just define our own hybrid of `@threads` and `@spawn` with `sticky = true`. That’s what [`@tspawnat`](https://github.com/carstenbauer/ThreadPinning.jl/blob/main/src/helper.jl#L189) is which I’ve added to ThreadPinning.jl yesterday (note that ThreadPools.jl also has a `@tspawnat` but, counterintuitively, it has `sticky = false`, see [this issue](https://github.com/tro3/ThreadPools.jl/issues/32)). So, you can now just do

```julia
using ThreadPinning
t = @tspawnat 3 f()
[...]
fetch(t)

```

to run `f()` on the third Julia thread without any task migration.

(Note that while the thread pinning part of ThreadPinning.jl only supports Linux, `@tspawnat` can, of course, be used on any system since it is only about making Julia tasks sticky.)

---

_[View the full topic](https://discourse.julialang.org/t/julia-1-7-says-it-can-switch-the-thread-your-task-is-on-how-often-does-that-happen-and-how-can-it-be-disabled/75373)._
