If arrays are value types and therefore get copied, then how are they not thread safe?

后端 未结 3 1792
感动是毒
感动是毒 2020-12-09 12:27

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

3条回答
  •  感情败类
    2020-12-09 13:10

    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!

提交回复
热议问题