gpt4 book ai didi

swift - Apple 对多线程引用和值类型的描述

转载 作者:搜寻专家 更新时间:2023-10-30 22:25:48 25 4
gpt4 key购买 nike

我正在阅读 Apple 的 documentation .我以为我知道何时选择值类型以及何时选择引用类型,但我又回到了 Swif101。文档说:

  • Value Types: The data will be used in code across multiple threads.
  • Reference Types: You want to create shared, mutable state

引用类型不是也可以跨多个线程共享吗?这两行有什么区别?

最佳答案

正如其他人指出的那样,引用类型总是传递一个指向对象的指针,这是您想要“共享的、可变的状态”(如您引用的文档所说)的理想选择。但是,很明显,如果您正在跨多个线程改变/访问引用类型,请确保同步您对它的访问(通过专用串行队列、读写器模式、锁等)。

不过,值类型有点复杂。是的,正如其他人所指出的那样,如果您将值类型作为参数传递给一个方法,然后在另一个线程上执行某些操作,那么您实际上是在使用该值类型的副本(Josh 关于复制的注释-写,尽管如此)。这确保了传递给方法的对象的完整性。很好(并且已被此处的其他答案充分涵盖)。

但是当你处理闭包时,它会变得更加复杂。例如,考虑以下内容:

struct Person {
var firstName: String
var lastName: String
}

var person = Person(firstName: "Rob", lastName: "Ryan")

DispatchQueue.global().async {
Thread.sleep(forTimeInterval: 1)
print("1: \(person)")
}

person.firstName = "Rachel"
Thread.sleep(forTimeInterval: 2)
person.lastName = "Moore"
print("2: \(person)")

显然,您通常不会 sleep ,但我这样做是为了说明这一点:也就是说,即使我们正在处理一个值类型和多个线程,您在闭包中引用的 person 是您在主线程(或运行它的任何线程)上处理的相同实例,而不是它的副本。如果您正在处理一个可变对象,那不是线程安全的。

我设计了这个例子来说明这一点,上面闭包中的 print 语句将报告“Rachel Ryan”,有效地显示了 Person 的状态值类型处于不一致状态。

对于使用值类型的闭包,如果您想享受值语义,您必须更改 async 调用以使用单独的变量:

let separatePerson = person
queue.async {
Thread.sleep(forTimeInterval: 1)
print("1: \(separatePerson)")
}

或者,更简单的方法是使用“捕获列表”,它指示闭包应捕获哪些值类型变量:

queue.async { [person] in
Thread.sleep(forTimeInterval: 1)
print("1: \(person)")
}

对于这些示例中的任何一个,您现在都在享受值语义,复制对象,并且 print 语句将正确报告“Rob Ryan”,即使原始的 person 对象正在另一个线程上发生变化。

因此,如果您正在处理值类型和闭包,则值类型可以跨线程共享,除非您显式使用捕获列表(或类似的东西)以享受值语义(即根据需要复制对象)。

关于swift - Apple 对多线程引用和值类型的描述,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38903359/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com