Why Dictionary crashed on concurrency write?

Here is the code:

var dict = [Int: Int]()
for i in 0...100 {
    DispatchQueue.global().async {
        dict[i] = i
    }
}

And I got this crash:

Xcode: 13.1
Swift: 5.0+
Mac: 12.1 M1

plz, it confuse me a lot

As a general rule in Swift, you must not access the same variable (or property, or so on) multiple times concurrently unless all the accesses are reads. Assignments to elements of a dictionary are considered to be modifications of the dictionary as a whole, so your code is in violation of that.

It is a goal of the concurrency feature that we've been working on to diagnose this problem at compile time. If you enable the strict concurrency checking in Swift 5.7, you should already get a diagnostic for this, at least if the dictionary is a local variable; global variables, including top-level variables in playgrounds, will not necessarily get the same diagnostic.

Swift does not currently provide a concurrent dictionary that allows different keys to be safely modified from multiple threads at once.

4 Likes

Thanks a lot! I understand it. Thanks!

Another question: Does an Int as a key store on heap or stack?

It’s not really “on the stack vs heap” so much as “with or without indirection”. That is, if you have an Int-keyed Dictionary (or an Array of Int) in Swift, the Int can be stored directly inline in the Dictionary’s storage, unlike in languages like Java or Objective-C where the collection just holds pointers, and those pointers point to the actual objects elsewhere on the heap.

(The dictionary or array storage itself though will normally be on the heap… but as a contiguous block of memory)

4 Likes

Thanks for you kind help.