当前位置: 首页 > 面试题库 >

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

傅鸿波
2023-03-14
问题内容

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

  • 值类型: 数据将在多个线程的代码中使用。
  • 参考类型: 您要创建共享的可变状态

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


问题答案:

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

但是,值类型稍微复杂一些。是的,正如其他人指出的那样,如果将值类型作为参数传递给在另一个线程上执行某操作的方法,则实际上是在使用该值类型的副本(乔什关于尽管写)。这样可以确保传递给该方法的对象的完整性。很好(并且这里的其他答案已充分覆盖了该问题)。

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

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即使原始person对象在另一个线程上发生了变异,该语句也将正确报告“
Rob Ryan” 。

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



 类似资料:
  • 问题内容: 基本上,我所做的是为州写一个枚举,我不仅希望能够像州一样访问它们,而且还希望访问它们的缩写以及它们是否是原始殖民地。 这似乎按我预期的那样工作。我可以 对于涉及枚举的特定情况,这是执行此操作的最佳方法,还是设置和格式化此枚举的更好方法?预先感谢所有人! 问题答案: 首先,枚举方法不应大写。它们是与其他方法一样的方法,具有相同的命名约定。 其次,您所做的并不是建立枚举的最佳方法。不要为每

  • 如何创建具有整数和字符串输入类型的?如果我创建一个: 这将是一个类型。如果我将其创建为: 这将是类型。我如何创建一个,它可以接受整数和字符串输入类型?谢谢。

  • 问题内容: 我有一个包含多个关系表的SQL DB。主表中的某些字段多次引用另一个表。例如,假设我有一个销售员数据库,负责多个州的销售。我的数据库具有State1,State2和State3的字段,所有字段都映射回一个States表。我一生都不知道如何编写查询以返回具有所有枚举状态的记录。如果我只需要一个State字段,我就会知道: 如何为我的所有“州”字段扩展此字段? 谢谢。 问题答案: 从每个唯

  • 本页包含内容: 值类型与引用类型的区别 Mutation(修改)在安全中扮演的角色 如何选择类型 Swift里面的类型分为两种: 值类型(Value Types):每个实例都保留了一分独有的数据拷贝,一般以结构体 (struct)、枚举(enum) 或者元组(tuple)的形式出现。 引用类型(Reference Type):每个实例共享同一份数据来源,一般以类(class)的形式出现。 在这篇博

  • 我正在开发基于spring+Hibernate的web应用程序。在这个应用程序中,我必须对数据库中的50000个可用记录进行计算。当前逻辑:- 循环0到50000(所有50000记录彼此独立) 选择第i个元素 对第i个元素执行计算(删除CALCULATION_TEMP表(如果存在),创建新表CALCULATION_TEMP并在CALCULATION_TEMP表中插入计算) 在步骤3表上进行一些计算

  • 问题内容: 我最近看到,可以声明一个返回类型,该返回类型也受接口限制。考虑以下类和接口: 我可以这样声明一个返回类型: 如果我从某个地方调用该方法,那么IDE会告诉我返回类型具有方法以及,但是仅当我在 Function 后面指向一个点时才这样: 有没有办法获得对这样一个对象的引用?我的意思是,如果我愿意做这样的事情: 我想有一个这样的参考(伪代码): 这在Java中是有可能的,还是我只能声明这样的