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)
}
複製代碼
運行結果會打印出來dog
、pig
而後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