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

相关文章
相关标签/搜索