Reading this I learn that:
Instances of value types are not shared: every thread gets its own copy.* That means that every thread can read and write t
Because Array is a value type, you're guaranteed that it has a single direct owner.
The issue comes from what happens when an array has more than one indirect owner. Consider this example:
Class Foo {
let array = [Int]()
func fillIfArrayIsEmpty() {
guard array.isEmpty else { return }
array += [Int](1...10)
}
}
let foo = Foo();
doSomethingOnThread1 {
foo.fillIfArrayIsEmpty()
}
doSomethingOnThread2 {
foo.fillIfArrayIsEmpty()
}
array has a single direct owner: the foo instance it's contained in. However, both thread 1 and 2 have ownership of foo, and transitively, of the array within it. This means they can both mutate it asynchronously, so race conditions can occur.
Here's an example of what might occur:
Thread 1 starts running
array.isEmpty evaluates to false, the guard passes, and execution will continue passed it
Thread 1 has used up its CPU time, so it's kicked off the CPU. Thread 2 is scheduled on by the OS
Thread 2 is now running
array.isEmpty evaluates to false, the guard passes, and execution will continue passed it
array += [Int](1...10) is executed. array is now equal to [1, 2, 3, 4, 5, 6, 7, 8, 9]
Thread 2 is finished, and relinquishes the CPU, Thread 1 is scheduled on by the OS
Thread 1 resumes where it left off.
array += [Int](1...10) is executed. array is now equal to [1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9]. This wasn't supposed to happen!