# Structure for Concurrent reads a single thread writing

**URL:** <https://discourse.julialang.org/t/structure-for-concurrent-reads-a-single-thread-writing/132811>\
**Category:** General Usage\
**Tags:** question, multithreading\
**Created:** [October 1, 2025, 11:10pm UTC](https://discourse.julialang.org/t/structure-for-concurrent-reads-a-single-thread-writing/132811 "2025-10-01T23:10:53Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Card1gan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/card1gan/32/218840_2.png) [@Card1gan](https://discourse.julialang.org/u/Card1gan)\
**Post date:** [October 1, 2025, 11:10pm UTC](https://discourse.julialang.org/t/structure-for-concurrent-reads-a-single-thread-writing/132811/1 "2025-10-01T23:10:53Z")

</div>

Firstly, I am relatively new to julia, but have been enjoying it so far.  
I am working on a parallel algorithm that requires multiple threads to read while one thread can update the vector, so my plan would be to use either a Ref or this atomic wrapper struct, but for some reason, both of these solutions end up blocking the main thread somehow which I’d think wouldn’t be possible from my MT experience in java.

In the below examples, it just simulates a bunch of reads and writes in parallel, but what is odd at least with testing here and in my actual case, when I use something like @btime or just run it multiple times with a large enough thread pool, it locks. What structures can I use to accomplish my goal while minimizing blocking?

- Edit: I should also note that I don’t care if it ends up in the correct ordering, as long as it updates often enough and doesn’t contain any invalid data. Sounds like immutable type stuff to me.

```julia
mutable struct AtomicWrapper{T}
    @atomic x::T
end

read(avec::AtomicWrapper) = @atomic avec.x
write(avec::AtomicWrapper, val) = @atomic avec.x = val

function f2()
    a = AtomicWrapper{Vector{Int}}(Int[])
    val = [1, 2, 3]
    write(a, val)

    thread = @spawn begin 
        i = 0
        while true
            if i % 10 == 0
                write(a, [])
            else
                write(a, [read(a)..., i])
            end
            i += 1
        end
    end

    @threads for _ in 1:1000
        println(read(a))
    end

    wait(thread)
end

function f()
    a = Ref{Vector{Int}}(Int[])
    val = [1, 2, 3]
    a[] = val
    worker = @spawn begin # Writes occurring while reads occurring
        i = 0
        # Since this is the only thread writing, no concurrent writes
        while true
            if i % 10 == 0
                a[] = []
            else
                a[] = [a[]..., i]
            end
            i += 1
        end
    end
    @threads for _ in 1:100
        println(a[]) # Concurrent Reads
    end
    wait(worker)
end

for _ in 1:10
    f()
end

```

---

<div class="post-metadata">

**Author:** ![WalterMadelim](https://avatars.discourse-cdn.com/v4/letter/w/3e96dc/32.png) [@WalterMadelim](https://discourse.julialang.org/u/WalterMadelim)\
**Post date:** [October 2, 2025, 12:15am UTC](https://discourse.julialang.org/t/structure-for-concurrent-reads-a-single-thread-writing/132811/2 "2025-10-02T00:15:16Z")

</div>

> [@Card1gan](#):
>
> `a[] = [a[]..., i]`

This line reads weird. What do you want to do?  
Why not `push!(a.x, i)`

---

<div class="post-metadata">

**Author:** ![sgaure](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sgaure/32/14779_2.png) [@sgaure](https://discourse.julialang.org/u/sgaure)\
**Post date:** [October 2, 2025, 5:59pm UTC](https://discourse.julialang.org/t/structure-for-concurrent-reads-a-single-thread-writing/132811/3 "2025-10-02T17:59:38Z")

</div>

In both `f` and `f2` you spawn an infinite loop, then wait for it to complete. It will likely take a very long time.

---

<div class="post-metadata">

**Author:** ![sgaure](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sgaure/32/14779_2.png) [@sgaure](https://discourse.julialang.org/u/sgaure)\
**Post date:** [October 2, 2025, 6:10pm UTC](https://discourse.julialang.org/t/structure-for-concurrent-reads-a-single-thread-writing/132811/4 "2025-10-02T18:10:26Z")

</div>

> [@WalterMadelim](#):
>
> > [@Card1gan](#):
> >
> > `a[] = [a[]..., i]`
> 
> This line reads weird. What do you want to do?  
> Why not `push!(a.x, i)`

A new vector is created and put into the `Ref`. A `push!` wouldn’t be thread safe. In the spec the assignment isn’t either, but I think it is atomic on all platforms julia runs on.

---

<div class="post-metadata">

**Author:** ![sgaure](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sgaure/32/14779_2.png) [@sgaure](https://discourse.julialang.org/u/sgaure)\
**Post date:** [October 2, 2025, 7:05pm UTC](https://discourse.julialang.org/t/structure-for-concurrent-reads-a-single-thread-writing/132811/5 "2025-10-02T19:05:20Z")

</div>

> [@Card1gan](#):
>
> ```julia-auto
> # Since this is the only thread writing, no concurrent writes
> while true
> if i % 10 == 0
> a[] = []
> else
> a[] = [a[]..., i]
> end
> i += 1
> end
> 
> ```

The manual disagrees that you don’t need an atomic annotation:

> Any field in a struct declaration can be decorated with `@atomic`, and then any write must be marked with `@atomic` also, and must use one of the defined atomic orderings (`:monotonic`, `:acquire`, `:release`, `:acquire_release`, or `:sequentially_consistent`).  
> [Multi-Threading · The Julia Language](https://docs.julialang.org/en/v1/manual/multi-threading/#man-atomics)

---

<div class="post-metadata">

**Author:** ![WalterMadelim](https://avatars.discourse-cdn.com/v4/letter/w/3e96dc/32.png) [@WalterMadelim](https://discourse.julialang.org/u/WalterMadelim)\
**Post date:** [October 2, 2025, 11:48pm UTC](https://discourse.julialang.org/t/structure-for-concurrent-reads-a-single-thread-writing/132811/6 "2025-10-02T23:48:45Z")

</div>

Why is the `...` collected by a `[]`? I thought `...` should only be collected by tuples, particularly in the context of function calls. He could had written `a[] = [a[]; i]`, which looks a lot more normal.

And, this is not assignment either.

```julia
julia> a = Ref([1]);

julia> @code_lowered a[] = [2]
CodeInfo(
1 ─ Base.setproperty!(b, :x, x)
│ %2 = b
└── return %2
)

```

You see the `setproperty!` is an in-place operation to the `b`, i.e. `a` in this example.  
At least from its naming convention…

---

<div class="post-metadata">

**Author:** ![ericphanson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ericphanson/32/215186_2.png) [@ericphanson](https://discourse.julialang.org/u/ericphanson)\
**Post date:** [October 3, 2025, 12:34am UTC](https://discourse.julialang.org/t/structure-for-concurrent-reads-a-single-thread-writing/132811/7 "2025-10-03T00:34:38Z")

</div>

> [@Card1gan](#):
>
> I am working on a parallel algorithm that requires multiple threads to read while one thread can update the vector

To me this sounds the use-case for a read-write lock, there is one implemented here: [ConcurrentUtilities.jl/src/rwlock.jl at fde04a11e78469d1ab6b5b4f1e74faf80bb50f3d · JuliaServices/ConcurrentUtilities.jl · GitHub](https://github.com/JuliaServices/ConcurrentUtilities.jl/blob/fde04a11e78469d1ab6b5b4f1e74faf80bb50f3d/src/rwlock.jl#L4)
