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