【问题标题】:Are swift higher order functions sync or async ? are they thread safe or not?swift 高阶函数是同步还是异步?它们是线程安全的吗?
【发布时间】:2023-03-20 08:01:01
【问题描述】:

像map、reduce、filter、sort这样的高阶函数是同步的还是异步的? 高阶函数是否是线程安全的?如果不是,那么我们如何使它们线程安全?通过在串行队列中实现它们?

【问题讨论】:

  • 据我所知,Swift 标准库中没有异步函数。
  • 没有什么是线程安全的,除非它明确声称是线程安全的。通常函数不是线程安全的,它们操作的数据结构需要是线程安全的。除非您使用 Grand Central Dispatch,否则一切都是同步的。

标签: swift


【解决方案1】:

是快速的高阶函数,如 map、reduce、filter、sort 吗?

同步

线程安全

不,以非混合方式使用是您的工作,否则将操作嵌入串行队列(主队列是串行的)

【讨论】:

  • 您不应该将主队列用于长时间运行的任务,因为它会阻塞 UI。使用专用的串行队列进行后台处理,然后在需要在 UI 上显示时(如果有的话)将结果分派到主队列。
  • 实际上这取决于操作的复杂程度,如果它像我们通常那样在主队列中使用,否则创建串行队列是唯一的其他选择并保证线程安全
【解决方案2】:

当您将一个函数或一个块传递给另一个函数时,请注意参数的类型:它可以是@escaping@nonescaping(后者是默认值,通常在定义中省略)。

非转义块肯定会在同一个线程上以同步方式调用。例如,所有列表操作高阶函数(映射、过滤器等)都是非转义的。事实上,其中一些函数可以被编译器内联和优化,根本没有任何函数调用。

转义块有点不同。如果你自己设计了一个高阶函数,并且碰巧将块存储在一个变量中以供稍后调用,编译器将强制你将其声明为@escaping。这些块可以在很晚之后从任何线程调用。

在处理系统或 API 调用时,您需要查看文档。例如,AVCaptureDevice.requestAccess(for:completionHandler:) 上的文档指出回调可以在任意线程上调用,因此您有责任确保您的 UI 代码在主线程上执行。你通常这样做:

AVCaptureDevice.requestAccess(for: .video, completionHandler: { (granted) in
    DispatchQueue.main.async {
        // Execute UI code here
    }
})

另一个例子是URLSessionTask 系列类,它们通常通过非主线程上的异步回调传递网络操作的结果。您可以利用您在不同线程上这一事实,或者您可以像上面的示例一样“返回”到主线程。

总而言之,这取决于高阶函数的设计者,所以简短的回答是:如果它是转义参数,则检查文档。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-09-08
    • 2018-11-16
    • 2019-01-17
    • 2015-07-21
    • 2011-09-16
    • 2020-05-15
    • 2020-02-21
    相关资源
    最近更新 更多