# Is \`@async\` memory safe?

**URL:** <https://discourse.julialang.org/t/is-async-memory-safe/66558>\
**Category:** General Usage\
**Tags:** multithreading\
**Created:** [August 17, 2021, 3:37pm UTC](https://discourse.julialang.org/t/is-async-memory-safe/66558 "2021-08-17T15:37:05Z")\
**Posts on this page:** 1\
**Showing post:** 8

<div class="post-metadata">

**Author:** ![tkf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkf/32/17635_2.png) [@tkf](https://discourse.julialang.org/u/tkf)\
**Post date:** [August 18, 2021, 7:48am UTC](https://discourse.julialang.org/t/is-async-memory-safe/66558/8 "2021-08-18T07:48:10Z")

</div>

Consider the following program:

```julia
using StructArrays

function f(a, b)
    v = StructVector((a, b))
    @sync begin
        @async push!(v, (1, 2))

        x = @inbounds v[end]
        @show x
    end
end

```

Is this program well-defined for `f(::Vector, ::Vector)`? Likely yes. (But there is no public API guaranteeing this is definitely the case.)

Is this program well-defined for `f(::AbstractVector, ::AbstractVector)`? No. This is because `push!(::AbstractVector, 1)` may contain an I/O; e.g., reading a file, accessing internet, or even just a `@debug` statement. In such case, the scheduler may decide to switch to the parent task while executing `push!(a, 1)` or `push!(b, 2)` in the child task. Now, in the parent task, the invariance of `StructVector` (e.g., the underlying arrays have consistent size) can completely be violated and no API can be expected to work.

The semantics of `@async` and `@spawn` tasks allow arbitrary interleaving of “pieces of code.” The only difference is that the granularity of the “pieces of code”. In `@async`, it’s the parts of the code delimited by the yield points (“I/O” operations). In `@spawn`, it’s individual machine instructions. So, this is why people tend to worry about the correctness of concurrent programs only when `@spawn` is used. More interleavings are possible and so it increases the possibility that bad things happen. However, since there is nothing in Julia language that makes sure certain function/method call does not contain a yield point [1], it is not correct to assume that manipulating a data structure from multiple `@async` tasks is safe, unless you read all the code reachable from the functions you are calling. (I guess it sounds rather like a FUD but I feel it is necessary for clarifying the current situation of concurrent programming in Julia.)

[1] In contrast, many other languages such as Python, JavaScript, C++, Rust, … that added coroutines after the language is designed tend to have `async`/`awit` keywords which clarify when the coroutine may yield to the scheduler. They have [another issue with it though](https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/).

---

_[View the full topic](https://discourse.julialang.org/t/is-async-memory-safe/66558)._
