DispatchQueue.main.async和DispatchQueue.main.sync之间的区别

Ama*_*ani 78 concurrency multithreading ios swift swift3

我一直在使用DispatchQueue.main.async很长一段时间来执行一些与UI相关的操作.但Swift提供了DispatchQueue.main.async和DispatchQueue.main.sync,两者都在主队列中执行.那么有谁可以告诉我他们之间的区别?我什么时候应该使用它们?先感谢您.

DispatchQueue.main.async {
    self.imageView.image = imageView
    self.lbltitle.text = ""

}

DispatchQueue.main.sync {
    self.imageView.image = imageView
    self.lbltitle.text = ""
}
Run Code Online (Sandbox Code Playgroud)

Ale*_*der 133

为什么要并发? 只要您向应用程序添加繁重的任务(如数据加载),就会降低UI工作速度,甚至冻结它.并发允许您"同时"执行2个或更多任务.这种方法的缺点是螺纹安全性并不总是那么容易控制.当不同的任务想要访问相同的资源时,例如尝试在不同的线程上更改相同的变量或访问已被不同线程阻止的资源.

我们需要注意一些抽象概念.

  • 队列.
  • 同步/异步任务性能.
  • 优先级.
  • 常见的麻烦.

队列.

必须是串行并发的.以及全球私人同时.

使用串行队列,任务将逐个完成,而并发队列,任务将同时执行,并将在意外的时间表上完成.与并发队列相比,同一组任务将占用串行队列的更多时间.

您可以创建自己的专用队列(串行并发)或使用已有的全局(系统)队列.该主队列是唯一的串行队列出所有的全局队列.

强烈建议不要执行在主队列上没有引用UI工作的繁重任务(从网络加载数据),而是在其他队列上执行这些任务以保持UI解冻并响应用户操作.如果我们在其他队列上更改UI,则可以根据不同的意外计划和速度进行更改.可以在需要之前或之后绘制一些UI元素.它可能会导致UI崩溃.我们还需要记住,由于全局队列系统队列,因此系统可以在其上运行一些其他任务.


服务质量/优先权.

队列也有不同的qos(服务质量),它设置任务执行优先级(从最高到最低)
:.userInteractive - 主队列
.userInitiated - 用户启动的任务,用户等待某些响应
.utility - 任务这需要一些时间并且不需要立即响应,例如使用数据
.background - 用于与可视部分无关且对完成时间不严格的任务.

还有

.default队列,它不传输qos信息.如果无法检测到qos,则将在.userInitiated.utility之间使用qos.

任务可以同步异步执行.

  • 同步函数仅在任务完成后才将控制权返回给当前队列.它会阻塞队列并等待任务完成.

  • 异步函数在任务发送到不同队列后立即将控制权返回给当前队列.它不会等到任务完成.它不会阻止队列.

常见的麻烦.

在预测并发应用程序时,程序员最常犯的错误如下:

  • 竞争条件 - 当应用程序工作时导致取决于代码部分执行的顺序.
  • 优先级倒置 - 当优先级较高的任务因某些资源被阻塞而等待较小的优先级任务完成时
  • 死锁 - 当一些队列无限期等待已被某些队列阻塞的源(变量,数据等)时.

切勿在主队列上调用同步功能.
如果你在主队列上调用sync函数,它将阻塞队列,并且队列将等待任务完成但是任务永远不会完成,因为它甚至无法启动,因为队列是已被封锁.它被称为死锁.

何时使用同步? 当我们需要等到任务完成时.我们确保某些函数/方法不是双重调用时的Fe.我们有同步并试图阻止它被双重调用,直到它完全结束.以下是此问题的一些代码:
如何找出导致IOS设备错误崩溃报告的原因?

  • QOS类-.userInteractive不是主队列。 (4认同)
  • 我认为“永远不要在主队列上调用同步功能”是正确的。在某些情况下,您可能会在主线程中调用同步,例如,当您有一个全局计数器需要每个对象使用并增加以下值时:dispatchQueue.sync {count + = 1; self.orderId = count} (3认同)
  • 说永远不应该在当前队列上调用sync()函数不是更准确吗?如果我理解正确的话,如果你在另一个队列中,那么在主队列上调用sync()并没有错。 (3认同)

And*_*kha 23

当您使用async它时,让调用队列继续运行而不等待执行调度块.相反,sync将使调用队列停止并等待您在块中调度的工作完成.因此sync会导致死锁.尝试DispatchQueue.main.sync从主队列运行,应用程序将冻结,因为调用队列将等待调度块结束,但它甚至无法启动(因为队列已停止并等待)

什么时候用sync?当您需要等待在不同队列上完成的任务时,然后才继续处理当前队列

使用同步的示例:

在串行队列上,您可以将其sync用作互斥锁,以确保只有一个线程能够同时执行受保护的代码段.

  • @茶杯很有趣。我只是想知道如果我们在那里调用“async”会有什么不同?我的意思是,既然之后线程上没有其他内容,那么它就没有什么区别。如果是`DispatchQueue.main.sync {block1}; DispatchQueue.main.sync {block2};` 那么它就有意义了。但是,当没有其他块时,我无法想到使用“DispatchQueue.main.sync {Oneblock}”比“DispatchQueue.main.async {Oneblock}”有什么好处。对于他们两个来说,他们将获得 mainQueue 优先级/即时性,并且没有任何事情会打扰他们。 (2认同)
  • 当您在主线程上时,@ Honey“因为线程之后没有其他东西了”,这是不正确的,它负责处理与应用程序的所有用户交互。因此,例如,用户可能在photoLibraryDidChange返回带有更新的数据源之前删除另一张照片,从而导致致命的不一致错误。 (2认同)

yoA*_*ex5 10

DispatchQueue.<>.sync 与 DispatchQueue.<>.async

[同步​​与异步]
[GCD]

GCD允许您执行任务synchronouslyasynchronously

synchronous(阻塞和等待)函数返回控制任务何时完成

asynchronous(调度并继续)函数立即返回一个控制,将任务调度到适当的队列,但不等待它完成。


归档时间:

查看次数:

54074 次

最近记录:

6 年,3 月 前