# Using atomic operations in Julia 1.6

**URL:** <https://discourse.julialang.org/t/using-atomic-operations-in-julia-1-6/86812>\
**Category:** General Usage\
**Tags:** question, threads\
**Created:** [September 5, 2022, 6:04pm UTC](https://discourse.julialang.org/t/using-atomic-operations-in-julia-1-6/86812 "2022-09-05T18:04:19Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![tictaccat](https://avatars.discourse-cdn.com/v4/letter/t/9f8e36/32.png) [@tictaccat](https://discourse.julialang.org/u/tictaccat)\
**Post date:** [September 5, 2022, 6:04pm UTC](https://discourse.julialang.org/t/using-atomic-operations-in-julia-1-6/86812/1 "2022-09-05T18:04:19Z")

</div>

I’d like to implement the following pattern:

```julia
mutable struct A
     @atomic x::Int
end
a = A(3)
@atomic a.x = 4 # in a multithreaded environment

```

However, I don’t want to drop compatibility with Julia 1.6 and it seems the `@atomic` macro was introduced in Julia 1.7. Is the above syntactic sugar / equivalent to something that can be expressed in Julia 1.6? Or is this ability fundamentally reliant on changes introduced in Julia 1.7?

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [September 5, 2022, 6:36pm UTC](https://discourse.julialang.org/t/using-atomic-operations-in-julia-1-6/86812/2 "2022-09-05T18:36:56Z")

</div>

The capability for atomic field access was introduced with [this PR](https://github.com/JuliaLang/julia/pull/37847) and is linked to the runtime - in particular the language level guarantees. Features are not backported, so there’s no equivalent providing the same guarantees in 1.6.

---

<div class="post-metadata">

**Author:** ![tictaccat](https://avatars.discourse-cdn.com/v4/letter/t/9f8e36/32.png) [@tictaccat](https://discourse.julialang.org/u/tictaccat)\
**Post date:** [September 5, 2022, 6:41pm UTC](https://discourse.julialang.org/t/using-atomic-operations-in-julia-1-6/86812/3 "2022-09-05T18:41:56Z")

</div>

How does my example differ from changing the type of `x` to `Threads.Atomic{Int}` and using the square brackets `x[]` when assigning to `x`? (edited)

---

<div class="post-metadata">

**Author:** ![tictaccat](https://avatars.discourse-cdn.com/v4/letter/t/9f8e36/32.png) [@tictaccat](https://discourse.julialang.org/u/tictaccat)\
**Post date:** [September 5, 2022, 6:44pm UTC](https://discourse.julialang.org/t/using-atomic-operations-in-julia-1-6/86812/4 "2022-09-05T18:44:06Z")

</div>

There are a lot of libraries doing fancy threaded stuff that support Julia 1.6 (the LTS), so I feel like I must be missing something as my use case is quite basic…

I guess my question is: what is the difference between `@atomic` and friends v.s. using `Threads.Atomic` and `atomic_add!` etc? Does one generalize the other? Or do they just do different things?

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [September 5, 2022, 8:47pm UTC](https://discourse.julialang.org/t/using-atomic-operations-in-julia-1-6/86812/5 "2022-09-05T20:47:31Z")

</div>

> [@tictaccat](#):
>
> How does my example differ from changing the type of `x` to `Threads.Atomic{Int}` and using the square brackets `x[]` when assigning to `x`? (edited)

`@atomic` supports more types, not just some bitintegers (most importantly, pointers/things that are stored as a pointer internally). Moreover, things like `x[] += 1` (that someone can write naively) can introduce subtle race conditions that `@atomic` prevents by requiring all accesses to go through that macro. As another benefit, `@atomic` supports memory ordering of accesses, which is more lightweight (and requires compiler support) than the heavy approach that `Atomic{T}` requires.

> [@tictaccat](#):
>
> There are a lot of libraries doing fancy threaded stuff that support Julia 1.6 (the LTS), so I feel like I must be missing something as my use case is quite basic…

Lots of threaded code can use locks and explicit synchronization points instead of atomic operations, or doesn’t need locks at all if no state is shared between threads. Atomic operations are no panacea either - sometimes you just need a heavier tool.

> [@tictaccat](#):
>
> I guess my question is: what is the difference between `@atomic` and friends v.s. using `Threads.Atomic` and `atomic_add!` etc? Does one generalize the other? Or do they just do different things?

I don’t know what your background is, but if you search for “memory ordering” you are sure to find lots of ressources about the topic. [This](https://www.llvm.org/docs/Atomics.html) may be of particular interest.

---

<div class="post-metadata">

**Author:** ![Palli](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/palli/32/3380_2.png) [@Palli](https://discourse.julialang.org/u/Palli)\
**Post date:** [September 5, 2022, 10:33pm UTC](https://discourse.julialang.org/t/using-atomic-operations-in-julia-1-6/86812/6 "2022-09-05T22:33:55Z")

</div>

> [@tictaccat](#):
>
> I don’t want to drop compatibility with Julia 1.6 and it seems the `@atomic` macro was introduced in Julia 1.7.

Why do you want to keep compatibility with 1.6? Since it’s not easily possible, maybe you can make a macro that would translate to a no-op on 1.6, and to `@atomic` on newer?

It would be dangerous if you run on 1.6 with threads (or your users), but if you can be sure they don’t I think it will be safe.

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [September 6, 2022, 4:35am UTC](https://discourse.julialang.org/t/using-atomic-operations-in-julia-1-6/86812/7 "2022-09-06T04:35:46Z")

</div>

> [@Palli](#):
>
> maybe ou can make a macro that would translate to a no-op on 1.6, and to `@atomic` on newer?

That’s arguably a bad idea, since the semantics of memory ordering are lost, which WILL introduce subtle bugs or even eliminate some code entirely, because the compiler can’t see that another thread is accessing the variable.

This is not easily backportable in any way that preserves the guarantees you want of it.

---

<div class="post-metadata">

**Author:** ![tictaccat](https://avatars.discourse-cdn.com/v4/letter/t/9f8e36/32.png) [@tictaccat](https://discourse.julialang.org/u/tictaccat)\
**Post date:** [September 6, 2022, 9:34am UTC](https://discourse.julialang.org/t/using-atomic-operations-in-julia-1-6/86812/8 "2022-09-06T09:34:28Z")

</div>

Thanks for your answers! I understand now that `@atomic` has some nice semantics for ensuring safety. However, assuming that I do use only safe operations for `Threads.Atonic` (e.g. atomic add rather than `+=`), is this going to be essentially _semantically_ equivalent to the analogous `@atomic` approach? My very rough understanding of the memory ordering stuff is that it should affect performance only rather than correctness, assuming the program is race-free? (You said `Threads.Atomic` was a more heavyweight approach – does that cotrespond to using the strictest memory ordering guarantee?)

---

<div class="post-metadata">

**Author:** ![Palli](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/palli/32/3380_2.png) [@Palli](https://discourse.julialang.org/u/Palli)\
**Post date:** [September 6, 2022, 1:39pm UTC](https://discourse.julialang.org/t/using-atomic-operations-in-julia-1-6/86812/9 "2022-09-06T13:39:43Z")

</div>

> [@Sukera](#):
>
> arguably a bad idea, since the semantics of memory ordering are lost

Right, why I mentioned it “would be dangerous”. But not without threading(?). So I’m not suggesting a macro for Julia Base, since it would be unsafe. Just thinking if people could do it. Better is to abandon Julia 1.6 LTS (e.g. if you need threading), and maybe 1.7 (or later) will be chosen as a new LTS, soon (I’ve not heard it confirmed).

---

<div class="post-metadata">

**Author:** ![jpsamaroo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jpsamaroo/32/46804_2.png) [@jpsamaroo](https://discourse.julialang.org/u/jpsamaroo)\
**Post date:** [September 6, 2022, 3:16pm UTC](https://discourse.julialang.org/t/using-atomic-operations-in-julia-1-6/86812/10 "2022-09-06T15:16:57Z")

</div>

Depending on what you’re doing, this might be fine, but it really depends. The main differences w.r.t ordering are that you can’t _control_ what ordering is used for `Threads.Atomic{T}`; for example, `atomic_add!` _always_ uses acquire-release ordering. If this is what you need, and your element type is supported, then it’ll be mostly equivalent to using `@atomic :acquire_release x.a += y` (and thus performance should be similar).

I recommend checking out `base/atomics.jl` in the Julia repository and cross-referencing with what’s in [LLVM Language Reference Manual — LLVM 16.0.0git documentation](https://llvm.org/docs/LangRef.html) to determine if the available calls suit your needs.

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [September 6, 2022, 3:28pm UTC](https://discourse.julialang.org/t/using-atomic-operations-in-julia-1-6/86812/11 "2022-09-06T15:28:09Z")

</div>

> [@tictaccat](#):
>
> (You said `Threads.Atomic` was a more heavyweight approach – does that cotrespond to using the strictest memory ordering guarantee?)

Heavyweight in terms of API - you’re forced to use the existing functions and can’t change their memory ordering, as well as only being able to use a limited number of types.

> [@Palli](#):
>
> and maybe 1.7 (or later) will be chosen as a new LTS, soon (I’ve not heard it confirmed).

None of that has been any topic of discussion, and LTS is not going to change so soon after it just got changed to 1.6 half a year ago.
