# Multithreading in Julia \>1.8 - Threadsafety of @threads vs @spawn

**URL:** <https://discourse.julialang.org/t/multithreading-in-julia-1-8-threadsafety-of-threads-vs-spawn/107159>\
**Category:** General Usage\
**Tags:** parallel, multithreading\
**Created:** [December 5, 2023, 10:51am UTC](https://discourse.julialang.org/t/multithreading-in-julia-1-8-threadsafety-of-threads-vs-spawn/107159 "2023-12-05T10:51:55Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![PatAsch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/patasch/32/46746_2.png) [@PatAsch](https://discourse.julialang.org/u/PatAsch)\
**Post date:** [December 5, 2023, 10:51am UTC](https://discourse.julialang.org/t/multithreading-in-julia-1-8-threadsafety-of-threads-vs-spawn/107159/1 "2023-12-05T10:51:55Z")

</div>

Hi there,

I have recently read the blog post about changes in @threads behavior from version 1.8 onwards: [PSA: Thread-local state is no longer recommended](https://julialang.org/blog/2023/07/PSA-dont-use-threadid/), and I am unsure if I do need to change up code that I wrote for a previous Julia version.

1. In my current code, I have multiple functions that use @threads without using the stated threadid, but I am using preallocated buffers that are filled during a loop.
2. I dont care at which index that buffer is filled.
3. The function inside the @threads loop mutates my arguments, but again I do not care in which order the arguments are getting mutated.

All my code has the following form:

```julia

Nchains = 96
# Nthreads == 8
Niterations = 10
T = 1000

for idx in 1:T
    buffer_argument1 = [BufferArgument1() for 1:Nchains]
    buffer_argument2 = [BufferArgument2() for 1:Nchains]
    buffer_output = [BufferOutput() for 1:Nchains]
    Base.Threads.@threads for Nchain in Base.OneTo(Nchains)
        for iter in 1:10
            buffer_output[Nchain] = func1!(buffer_argument1[Nchain], buffer_argument2[Nchain])
        end
    end
    compute_some_summary_statistics(buffer_output)
end

```

Do I need to change @threads to a version working with @spawn, or is this safe going forward? I tried to find the solution for this based on the multiple open questions already on discourse, but am still unsure about the solution.

---

<div class="post-metadata">

**Author:** ![foobar\_lv2](https://avatars.discourse-cdn.com/v4/letter/f/ee59a6/32.png) [@foobar\_lv2](https://discourse.julialang.org/u/foobar_lv2)\
**Post date:** [December 5, 2023, 11:44am UTC](https://discourse.julialang.org/t/multithreading-in-julia-1-8-threadsafety-of-threads-vs-spawn/107159/2 "2023-12-05T11:44:20Z")

</div>

Your pattern should be safe: multi-thread over Nchains many items, and you allocate all state Nchains many times.

The problem is with a different kind of pattern: In many cases, one needs large amounts of reusable temporary internal state, and it would be prohibitive to allocate that Nchains many times. Instead, one wants to allocate as few as possible instances of the internal state and reuse them. The old canonical solution was `tmp_states = [makeTmpState() for i=1:Threads.nthreads()]` and later use `tmp_state = tmp_states[Threads.threadid()]` and that is what got broken.

As far as I know, there exists no canonical solution yet (i.e. the community has not yet found consensus what the standard solution should be).

---

<div class="post-metadata">

**Author:** ![PatAsch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/patasch/32/46746_2.png) [@PatAsch](https://discourse.julialang.org/u/PatAsch)\
**Post date:** [December 5, 2023, 12:16pm UTC](https://discourse.julialang.org/t/multithreading-in-julia-1-8-threadsafety-of-threads-vs-spawn/107159/3 "2023-12-05T12:16:26Z")

</div>

> [@foobar\_lv2](#):
>
> The problem is with a different kind of pattern …

That makes sense, thank you! As long as I do not depend on internal instances, I should be safe. Just to finalize this: If I had, as an additional argument, a shared argument **that is not mutated during the loop** would this create any additional allocations?

For example:

```julia
Nchains = 96
shared_argument = SharedArgument()
buffer_output = [BufferOutput() for 1:Nchains]

Base.Threads.@threads for Nchain in Base.OneTo(Nchains)
     buffer_output[Nchain] = func1(shared_argument)
end

```

---

<div class="post-metadata">

**Author:** ![foobar\_lv2](https://avatars.discourse-cdn.com/v4/letter/f/ee59a6/32.png) [@foobar\_lv2](https://discourse.julialang.org/u/foobar_lv2)\
**Post date:** [December 5, 2023, 12:19pm UTC](https://discourse.julialang.org/t/multithreading-in-julia-1-8-threadsafety-of-threads-vs-spawn/107159/4 "2023-12-05T12:19:46Z")

</div>

> [@PatAsch](#):
>
> a shared argument **that is not mutated during the loop** would this create any additional allocations?

That is completely safe and fine and performant.
