# Execute Function for each Julia Thread

**URL:** <https://discourse.julialang.org/t/execute-function-for-each-julia-thread/133889>\
**Category:** General Usage\
**Tags:** ccall, parallel, multithreading, ffi\
**Created:** [November 14, 2025, 7:59pm UTC](https://discourse.julialang.org/t/execute-function-for-each-julia-thread/133889 "2025-11-14T19:59:43Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Chrysoberyl](https://avatars.discourse-cdn.com/v4/letter/c/ed655f/32.png) [@Chrysoberyl](https://discourse.julialang.org/u/Chrysoberyl)\
**Post date:** [November 14, 2025, 7:59pm UTC](https://discourse.julialang.org/t/execute-function-for-each-julia-thread/133889/1 "2025-11-14T19:59:43Z")

</div>

I have an external library which requires thread local resources to function. For every thread Julia creates, it must notify this library via an `initialize_thread_local()` function. Is there a way to run this code for each OS thread that Julia spawns? `@everywhere` only runs on each process and not thread. Is the best option `Threads.@threads :static`?

---

<div class="post-metadata">

**Author:** ![asinghvi17](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/asinghvi17/32/8272_2.png) [@asinghvi17](https://discourse.julialang.org/u/asinghvi17)\
**Post date:** [November 14, 2025, 8:59pm UTC](https://discourse.julialang.org/t/execute-function-for-each-julia-thread/133889/2 "2025-11-14T20:59:30Z")

</div>

The best option is probably a TaskLocalValue (`OncePerTask` on Julia 1.12+) from TaskLocalValues.jl. (That assumes this is a C-style “threading context”  
that you pass into the ccalls you’re making).

Julia tasks can migrate threads, so it’s not safe to simply assume that a task will remain on the thread it started on.

---

<div class="post-metadata">

**Author:** ![Chrysoberyl](https://avatars.discourse-cdn.com/v4/letter/c/ed655f/32.png) [@Chrysoberyl](https://discourse.julialang.org/u/Chrysoberyl)\
**Post date:** [November 14, 2025, 9:26pm UTC](https://discourse.julialang.org/t/execute-function-for-each-julia-thread/133889/3 "2025-11-14T21:26:28Z")

</div>

In this case I do not need to track any thread local context. The external library sets up thread local contextes when I call `initialize_thread_local()`

---

<div class="post-metadata">

**Author:** ![asinghvi17](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/asinghvi17/32/8272_2.png) [@asinghvi17](https://discourse.julialang.org/u/asinghvi17)\
**Post date:** [November 15, 2025, 12:54am UTC](https://discourse.julialang.org/t/execute-function-for-each-julia-thread/133889/4 "2025-11-15T00:54:12Z")

</div>

Hmm, that might be tricky with Julia’s mutlithreading. Thankfully StableTasks.jl provides a `@spawnat` macro that you can use to specify that your task should stick to the indicated thread.

If you just need to run a single initializer function per thread, here’s what you could do:

```julia
using StableTasks: @spawnat
tasks = [@spawnat i initialize_thread_local() for i in 1:Threads.nthreads(:default)]
foreach(fetch, tasks) # wait for all tasks to finish  

```

and then you could make sure that all your other library calls also use `@spawnat` - you don’t want the thread-local state getting corrupted by a Julia task suddenly switching threads.

But many C libraries like this have “reentrant” APIs so that is worth exploring if it’s an option.

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [November 15, 2025, 1:54am UTC](https://discourse.julialang.org/t/execute-function-for-each-julia-thread/133889/5 "2025-11-15T01:54:34Z")

</div>

I think what you want is [OncePerThread](https://docs.julialang.org/en/v1/base/base/#Base.OncePerThread)

---

<div class="post-metadata">

**Author:** ![Chrysoberyl](https://avatars.discourse-cdn.com/v4/letter/c/ed655f/32.png) [@Chrysoberyl](https://discourse.julialang.org/u/Chrysoberyl)\
**Post date:** [November 15, 2025, 4:01am UTC](https://discourse.julialang.org/t/execute-function-for-each-julia-thread/133889/6 "2025-11-15T04:01:52Z")

</div>

`OncePerThread` seems to be the right tool. I tried to run it in a module’s ` __init__ ` function:

```julia
    Threads.@threads :static for _ = 1:Threads.nthreads()
        @info "Static initialize: $(Threads.threadid())"
    end

    thread_local_initializer = Base.OncePerThread() do
        @info "Perthread initialize: $(Threads.threadid())"
    end
    thread_local_initializer()

```

but it printed out

```julia-auto
[ Info: Static initialize: 2
[ Info: Perthread initialize: 1

```

indicating that the second initializer was not run for thread #2. Is there a reason why it would not run on #2?

---

<div class="post-metadata">

**Author:** ![abraemer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/abraemer/32/51403_2.png) [@abraemer](https://discourse.julialang.org/u/abraemer)\
**Post date:** [November 15, 2025, 7:02am UTC](https://discourse.julialang.org/t/execute-function-for-each-julia-thread/133889/7 "2025-11-15T07:02:36Z")

</div>

> [@Chrysoberyl](#):
>
> Is there a reason why it would not run on #2?

I think you just didn’t call it in Thread 2. The way I think `OncePerThread` is essentially by lazy caching. So calling it multiple times on the _same_ thread does not invoke the wrapped function multiple times:

```julia-auto
    thread_local_initializer = Base.OncePerThread() do
        @info "Perthread initialize: $(Threads.threadid())"
    end
    thread_local_initializer()
    thread_local_initializer()
    thread_local_initializer()

```

Should only print once.

If you wish to initialize all threads then you’ll have ti call this on all threads.

> [@Chrysoberyl](#):
>
> The external library sets up thread local contextes when I call `initialize_thread_local()`

This sounds to me like this library would not like Julia migrating Tasks between threads, so you’ll probably have to use `static` scheduling? In that case you could just put a call to `initialize_thread_local()` at the top of the threaded loop’s body to ensure that the thread the Task runs in is initialized. That would probably be the safest option.
