iOS中的同步与异步队列

Posted

技术标签:

【中文标题】iOS中的同步与异步队列【英文标题】:Sync vs Async Queue in iOS 【发布时间】:2020-02-03 13:14:22 【问题描述】:

我对 JS 有一些想法,并且正在使用 ios

我正在阅读 this blog 并且对 Swift 中的异步和同步感到困惑(尽管我感觉它在 IOS 和 javascript 中是相同的)但无论如何

import UIKit 

func smile () 
    print('1')


func love() 
    print('2')


//Serial Queue

let queue = DispatchQueue(label: 'SerialQueue')

queue.async 
    for _ in 1...5 
     smile()
  


 queue.async 
    for _ in 1...5 
     love()
   
 

这会记录这样的事情 1

1
1
1
1
2
2
2
2
2

想想这个例子,如果它是同步而不是异步,那么输出会是一样的吗?那么上面使用 async 有什么用呢?

另外,在 JS 中我们需要等待。迅速我们不需要做任何事情?有人可以通过快速给出异步和等待的例子来向我解释吗?

【问题讨论】:

我认为你会受益于更多地研究 async/await(如在 javascript 中看到的,以及在其他语言中看到的),并准确地了解它的作用。 【参考方案1】:

由于您对两个作品使用相同的队列,因此第二个异步块在第一个块结束之前不会开始执行。不管是异步的还是串行的。

如果您在两个队列之间添加打印语句,您将看到.async.sync 之间的真正区别。像这样:

queue.async 
    for _ in 1...100 
          self.smile()
    

print("Finished printing smiles")
queue.async 
    for _ in 1...100 
          self.love()
    

之前的代码可能会在开始打印微笑之前打印“完成打印微笑”!这是因为异步工作会立即返回并继续执行代码。


让我们看看如果使用同步队列更改队列会发生什么:

queue.sync 
    for _ in 1...100 
          self.smile()
    

print("Finished printing smiles")
queue.sync 
    for _ in 1...100 
          self.love()
    

是的。现在同步队列在关闭完成之前等待,然后再继续。所以,你会得到 100 个微笑,然后是“完成打印的微笑”。


如果你想实现并发,就是这样,两个代码块同时执行(但不完全相同,因为那将是并行性),你必须使用两个不同的队列,或者指定@987654325队列配置中的@参数:

override func viewDidLoad() 

    let queue = DispatchQueue(label: "SerialQueue")
    let queue2 = DispatchQueue(label: "AnotherQueue")

    queue.async 
        for _ in 1...100 
              self.smile()
        
    
    print("Finished printing smiles")
    queue2.async 
        for _ in 1...100 
              self.love()
        
    

如您所见,这里的顺序是混乱的,并且会因执行而异。那是因为两个队列同时运行。

此代码的另一个等价物是:

let queue = DispatchQueue(label: "ConcurrentQueue", attributes: .concurrent)

queue.async 
    for _ in 1...100 
          self.smile()
    

print("Finished printing smiles")
queue.async 
    for _ in 1...100 
          self.love()
    

【讨论】:

【参考方案2】:

@loufranco 和@Roberto 已经详细回答了。

您也可以在单个OperationQueue 上添加不同的BlockOperation 来实现此目的。

好像你会在这个场景中看到:

let queue = OperationQueue()

let operation1 = BlockOperation 
    for _ in 1...5 
     smile()
  

print("Done")
let operation2 = BlockOperation 
    for _ in 1...5 
     love()
   
 

queue.addOperation (operation1)
queue.addOperation (operation2)

输出是:

如果你要在 operation1 上添加 operation2 依赖:

operation2.addDependency(operation1)
queue.addOperation (operation1)
queue.addOperation (operation1)

输出是:

【讨论】:

【参考方案3】:

当您使用同步时,它会在队列的线程中执行,但同步在完成之前不会返回。 async 立即返回。

因为你有一个串行队列,所以打印是一样的,但是调用函数可以在队列完成打印之前返回。如果它是同步的,则调用函数将等待打印完成。

Swift 中还没有 async/await 的概念。这不是这里发生的事情(或在同步情况下)

如果您想查看差异,请将 sleep 放入块中并在队列调用之外打印。

【讨论】:

以上是关于iOS中的同步与异步队列的主要内容,如果未能解决你的问题,请参考以下文章

GCD使用 串行并行队列 与 同步异步执行的各种组合 及要点分析

# 进程/线程/协程 # IO:同步/异步/阻塞/非阻塞 # greenlet gevent # 事件驱动与异步IO # SelectPollEpoll异步IO 以及selectors模块 # (示

同步/异步 异步回调 协成 线程队列

并发与同步异步的概念

js中的异步与同步,解决由异步引起的问题

20230515学习笔记——js中的同步任务与异步任务,宏任务与微任务