加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

swift – Apple对具有多个线程的引用和值类型的描述

发布时间:2020-12-14 02:27:09 所属栏目:百科 来源:网络整理
导读:我正在阅读Apple的 documentation.我以为我知道何时选择值类型以及何时选择引用类型,但我回到Swif101.文件说: Value Types: The data will be used in code across multiple threads. Reference Types: You want to create shared,mutable state 多个线程之
我正在阅读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关于copy-on-的注释)写,尽管如此).这可确保传递给方法的对象的完整性.那很好(这里的其他答案已经充分涵盖了).

但是当你处理闭包时它会变得更复杂.例如,考虑以下因素:

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)")

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

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

对于使用值类型的闭包,如果要享受值语义,则必须更改该异步调用以使用单独的变量:

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对象正在另一个线程上进行变异.

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读