# Length of Dict is not thread safe

**URL:** <https://discourse.julialang.org/t/length-of-dict-is-not-thread-safe/74906>\
**Category:** General Usage\
**Tags:** multithreading\
**Created:** [January 20, 2022, 5:30am UTC](https://discourse.julialang.org/t/length-of-dict-is-not-thread-safe/74906 "2022-01-20T05:30:56Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Jason89757](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jason89757/32/7483_2.png) [@Jason89757](https://discourse.julialang.org/u/Jason89757)\
**Post date:** [January 20, 2022, 5:30am UTC](https://discourse.julialang.org/t/length-of-dict-is-not-thread-safe/74906/1 "2022-01-20T05:30:56Z")

</div>

I’m trying to write something providing mysql-like functions: insert one row then return id.

```julia
d = Dict{Int64,Int64}()
Threads.@threads for i in 1:10000
  if !haskey(d,i)
    d[i] = length(d)+1
  end
end

julia> length(d)
5670

julia> collect(d)
ERROR: ArgumentError: destination has fewer elements than required
Stacktrace:
 [1] copyto!(dest::Vector{Pair{Int64, Int64}}, src::Dict{Int64, Int64})
   @ Base ./abstractarray.jl:897
 [2] _collect
   @ ./array.jl:715 [inlined]
 [3] collect(itr::Dict{Int64, Int64})
   @ Base ./array.jl:709
 [4] top-level scope
   @ REPL[5]:1

```

I can use an extra Vector to fix this, but is there another better solution?

---

<div class="post-metadata">

**Author:** ![goerch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/goerch/32/29122_2.png) [@goerch](https://discourse.julialang.org/u/goerch)\
**Post date:** [January 20, 2022, 5:42am UTC](https://discourse.julialang.org/t/length-of-dict-is-not-thread-safe/74906/2 "2022-01-20T05:42:36Z")

</div>

How to prevent data races: [Multi-Threading · The Julia Language](https://docs.julialang.org/en/v1/manual/multi-threading/#Data-race-freedom)

---

<div class="post-metadata">

**Author:** ![Jason89757](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jason89757/32/7483_2.png) [@Jason89757](https://discourse.julialang.org/u/Jason89757)\
**Post date:** [January 20, 2022, 6:03am UTC](https://discourse.julialang.org/t/length-of-dict-is-not-thread-safe/74906/3 "2022-01-20T06:03:43Z")

</div>

Thanks a lot!  
Struct a type with data and lock can fix this.

---

<div class="post-metadata">

**Author:** ![Jason89757](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jason89757/32/7483_2.png) [@Jason89757](https://discourse.julialang.org/u/Jason89757)\
**Post date:** [January 20, 2022, 6:14am UTC](https://discourse.julialang.org/t/length-of-dict-is-not-thread-safe/74906/4 "2022-01-20T06:14:26Z")

</div>

found a solution:  
[https://github.com/wherrera10/ThreadSafeDicts.jl](https://github.com/wherrera10/ThreadSafeDicts.jl)

---

<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:** [January 20, 2022, 6:55am UTC](https://discourse.julialang.org/t/length-of-dict-is-not-thread-safe/74906/5 "2022-01-20T06:55:34Z")

</div>

I suggest just protect the plain `Dict` with a `ReentrantLock`. Protecting the integrity of the dictionary itself is not sufficient for the correctness of your program. Consider the following scenario involving two tasks T1 and T2:

- T1 wants a new id for key 123
- T2 wants a new id for key 456
- T1 calls `length(d)`, get 41
- T2 calls `length(d)`, get 41
- T1 inserts `d[123]= 42`
- T2 inserts `d[456]= 42`

Now two keys refer to the same ID and no keys have id 43.

The code in the OP would be fine if you put a lock around `if !haskey(d,i) ... end`.

There are a lot of clever techniques to make this efficient. But reasoning about concurrent programs requires a lot more thinking than some comments fit in a discourse post.

---

<div class="post-metadata">

**Author:** ![lawless-m](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lawless-m/32/30869_2.png) [@lawless-m](https://discourse.julialang.org/u/lawless-m)\
**Post date:** [January 20, 2022, 8:08am UTC](https://discourse.julialang.org/t/length-of-dict-is-not-thread-safe/74906/6 "2022-01-20T08:08:43Z")

</div>

I don’t want to be deliberately snarky but “what made you think it would be?”

When entering the world of concurrency, one has to think carefully.
