# Reading from empty dictionary isn't thread-safe

**URL:** <https://discourse.julialang.org/t/reading-from-empty-dictionary-isnt-thread-safe/134189>\
**Category:** General Usage\
**Tags:** question\
**Created:** [November 28, 2025, 3:40pm UTC](https://discourse.julialang.org/t/reading-from-empty-dictionary-isnt-thread-safe/134189 "2025-11-28T15:40:48Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Fabian\_Matesa](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fabian_matesa/32/213574_2.png) [@Fabian\_Matesa](https://discourse.julialang.org/u/Fabian_Matesa)\
**Post date:** [November 28, 2025, 3:40pm UTC](https://discourse.julialang.org/t/reading-from-empty-dictionary-isnt-thread-safe/134189/1 "2025-11-28T15:40:48Z")

</div>

As the title suggests, trying to call `get!` on an empty dictionary in multiple threads concurrently will cause an error to be thrown. Example:

```julia-auto
dd = Dict()
Threads.@threads for i in 1:1000
    get!(dd, i, 2)
end

```

The issue I have with this (in julia 1.12) is that I have a parallelized loop in which a function as part of its logic checks whether two values are approximately the same. To check that, it needs tolerance values for the given numeric type, which are stored inside a constant dictionary object in the `ReachabilityBase` package. However, I haven’t set any tolerance values, meaning that dictionary is empty. The expected behavior there is to use default tolerance values, but instead I get the following error: `AssertionError: Multiple concurrent writes to Dict detected!`

Apparently the `get!` function calls the `ht_keyindex2_shorthash!` function, which in turn rehashes the dictionary if it’s empty. What is the reasoning behind this? I wouldn’t expect a read operation to not be thread-safe.

---

<div class="post-metadata">

**Author:** ![GunnarFarneback](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gunnarfarneback/32/1827_2.png) [@GunnarFarneback](https://discourse.julialang.org/u/GunnarFarneback)\
**Post date:** [November 28, 2025, 3:48pm UTC](https://discourse.julialang.org/t/reading-from-empty-dictionary-isnt-thread-safe/134189/2 "2025-11-28T15:48:13Z")

</div>

For what it’s worth, `get!` is not a read-only operation. Did you mean to write `get`?

---

<div class="post-metadata">

**Author:** ![Wikunia](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wikunia/32/2180_2.png) [@Wikunia](https://discourse.julialang.org/u/Wikunia)\
**Post date:** [November 28, 2025, 4:10pm UTC](https://discourse.julialang.org/t/reading-from-empty-dictionary-isnt-thread-safe/134189/3 "2025-11-28T16:10:07Z")

</div>

Yeah I had the same point. Maybe the biggest wondering I have is why it uses `get!` and not `get` here:

> <https://github.com/JuliaReach/ReachabilityBase.jl/blob/1b49afc3cdb950556322f1961aa160089a20e526/src/Comparison/tolerance.jl#L86-L89>

---

<div class="post-metadata">

**Author:** ![Fabian\_Matesa](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fabian_matesa/32/213574_2.png) [@Fabian\_Matesa](https://discourse.julialang.org/u/Fabian_Matesa)\
**Post date:** [November 28, 2025, 4:49pm UTC](https://discourse.julialang.org/t/reading-from-empty-dictionary-isnt-thread-safe/134189/4 "2025-11-28T16:49:08Z")

</div>

Usually I would use `get`, but in my case I depend on a core julia package which uses `get!`. Maybe a more appropriate question would be why `get!` even exists?

---

<div class="post-metadata">

**Author:** ![barucden](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/barucden/32/26154_2.png) [@barucden](https://discourse.julialang.org/u/barucden)\
**Post date:** [November 28, 2025, 4:58pm UTC](https://discourse.julialang.org/t/reading-from-empty-dictionary-isnt-thread-safe/134189/5 "2025-11-28T16:58:09Z")

</div>

`get!` is very convient:

```julia
cache = Dict{String, String}()
value = get!(cache, "key") do 
    # this function is called only when "key" is missing in cache
    return fetch_value("key")
end

```

---

<div class="post-metadata">

**Author:** ![GunnarFarneback](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gunnarfarneback/32/1827_2.png) [@GunnarFarneback](https://discourse.julialang.org/u/GunnarFarneback)\
**Post date:** [November 28, 2025, 5:23pm UTC](https://discourse.julialang.org/t/reading-from-empty-dictionary-isnt-thread-safe/134189/6 "2025-11-28T17:23:07Z")

</div>

> [@Fabian\_Matesa](#):
>
> Usually I would use `get`, but in my case I depend on a core julia package which uses `get!`

Then I suggest you open an issue with that package to ask if they can provide a read-only option for the operation you need.

> [@Fabian\_Matesa](#):
>
> Maybe a more appropriate question would be why `get!` even exists?

No, that is not an appropriate question. `get!` is one of the frequently used operations you need to perform on a dictionary. Yes, you can build it up from other primitives but doing so every time you need `get!` would be repetitive and a potential source of buggy and less-than optimal implementations.

> [@Wikunia](#):
>
> Maybe the biggest wondering I have is why it uses `get!` and not `get` here:

That is a very good question though. I have a hard time seeing the point.

---

<div class="post-metadata">

**Author:** ![simsurace](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simsurace/32/30216_2.png) [@simsurace](https://discourse.julialang.org/u/simsurace)\
**Post date:** [November 29, 2025, 3:09pm UTC](https://discourse.julialang.org/t/reading-from-empty-dictionary-isnt-thread-safe/134189/7 "2025-11-29T15:09:02Z")

</div>

One of the points of `get!` is to only do the hashing of the key once.
