swift值類型的線程安全

swift中的值類型

swift中不一樣於oc,數組和字典等都被定義爲了值類型,而與之對應的類屬於引用類型。固然值類型還包括結構體和枚舉。值類型有一個優勢就是線程安全,本篇也只討論其線程安全的問題。swift

一個有趣的例子

有這樣一段代碼,判斷下輸出結果以及會不會crash:數組

let queue = DispatchQueue.global()

var animals = ["dog", "cat", "pig"]

queue.async {
    let count = animals.count
    for index in 0 ..< count {
        print("\(animals[index])")
        Thread.sleep(forTimeInterval: 1)
    }
}

queue.async {
    Thread.sleep(forTimeInterval: 0.5)
    animals.remove(at: 0)
}
複製代碼

運行結果會打印出來dogpig而後crash掉了,報錯信息:安全

Thread 4: Fatal error: Index out of range。
複製代碼

緣由就是咱們在讀取數組第二個元素時,第一個元素被移除掉了,因此會打印出來pig。而後當讀取第三個元素時,數組內已無第三個元素,因此就會越界crash。那麼是否是就意味着值類型並非線程安全的呢?bash

真實的線程安全

經過上面的例子不難看出值類型的數組在這種多線程讀寫的狀況下並非線程安全的。咱們所說的線程安全是這樣的:多線程

queue.async { [animals] in
    let count = animals.count
    for index in 0 ..< count {
        print("\(animals[index])")
        Thread.sleep(forTimeInterval: 1)
    }
}
複製代碼

經過對這段代碼的修改咱們就能夠獲得想要的結果,而且不會crash。由於此時在新的線程中會copy出一份新的animals。因此當線程會copy值類型內容時是線程安全的,其餘狀況會存在線程不安全的隱患,咱們使用時應當注意。async

相關文章
相關標籤/搜索