当运行到协程 await 语句时,当前线程处于一种什么样的状态?

2023-05-23 20:09:58 +08:00
 James369

最近学习协程很困惑。以下是 swift 代码,还是没大明白协程的工作过程:

func fetchData() async -> String {
    print("Start fetching data")
    
    // 模拟异步操作,使用 Task.sleep 等待 2 秒钟
    await Task.sleep(2_000_000_000)
    
    print("Data fetching complete")
    return "Data"
}

func processData() async {
    print("Start processing data")
    
    let data = await fetchData() // 等待 fetchData() 异步操作的完成
    
    print("Data processing complete. Received: \(data)")
}

print("Before calling processData")

Task {
    await processData() // 调用异步函数 processData()
}

print("After calling processData")

疑问:

  1. 协程本质是实现了串行还是并行运行?
  2. 当运行到协程 await 语句时,当前线程是挂起状态吗。(按照资料上说,协程不会阻塞当前线程)
  3. 这个 Task 是否就是开启一个新的线程执行?
4248 次点击
所在节点    程序员
30 条回复
J1sen
2023-05-24 15:05:26 +08:00
可以学习 C++20 协程,比较底层,自己实现一下 task 这些类型就明白了。swift 这种是无栈协程,无栈协程就相当于同一个函数调用多次,但是执行的代码不一样了。一般 await 表示让出执行权,一般就是两种选择,把执行权交给调度器,让调度器去选择协程执行,或者是直接把执行权给另外一个协程。而让出执行权有两种方式,一种是函数返回,一种是函数调用。一般来说回到调度器是通过函数返回,而 await 另外一个协程是通过直接调用对应的协程函数实现的,await 的协程调用结束的时候又会把执行权交给原来的协程。 https://lewissbaker.github.io 可以看看这里的文章,讲的非常清晰
hankai17
2023-05-24 15:14:03 +08:00
1. 串行运行
2. 协程调度设计应该类似于 有个全局协程队列 不断地循环执行 如果所有协程都运行完 或者 协程睡眠 /等待 那么线程就处于 sleep 态 否则仍然是 running 态
Leviathann
2023-05-24 15:31:06 +08:00
无栈协程等价于给线程池 /eventloop 提交 task
不相关的两个协程之间,你的线程池 /eventloop 是多线程就可以是并行,是单线程就是串行
await 之前与之后部分则保证则是串行
xausky
2023-05-24 16:38:25 +08:00
await 还好 yield 才是神奇的操作
chtcrack
2023-05-24 16:44:11 +08:00
异步和多线程都是用来处理并发任务的技术,但它们的实现方式和目的略有不同。

多线程是指将一个进程中的工作分成多个独立的线程,每个线程可以并行执行不同的任务,从而实现并发处理。在多线程中,每个线程都有自己的执行上下文和堆栈,可以在不同的时间、不同的 CPU 核心上执行任务,从而提高程序的并发性能。

异步是指在执行任务时,不需要等待当前任务完成,而是可以在等待期间继续执行其他任务。异步通常使用回调、协程、事件或者消息等机制来实现,它的目的是提高程序的响应性能和吞吐量。

因此,多线程和异步的区别在于它们的实现方式和目的:

多线程是通过将任务分配到多个线程中并行执行,来提高程序的并发性能。
异步是通过在等待期间继续执行其他任务,来提高程序的响应性能和吞吐量。
需要注意的是,多线程和异步并不是互斥的,它们可以同时使用,以达到更好的性能优化效果。例如,在一个多线程的程序中,可以使用异步方式来处理某些任务,以避免线程阻塞和资源浪费。又或者,在一个异步的程序中,可以使用多线程来加速某些任务的执行,以提高程序的并发性能。

总之,多线程和异步都是并发编程中非常重要的技术,程序员需要根据具体的需求和场景,来选择合适的技术来处理并发任务。 现在都有 chatgpt 了,它比大多数人都懂得多,没事可以多问问它..
dearmymy
2023-05-24 16:51:29 +08:00
如果会汇编就比较好理解。得稍微了解下 call 函数过程
实际上协程核心代码就那几行汇编。
heroin80s
2023-05-24 17:07:32 +08:00
分清楚 并行和并发
await 的时候程序指针改变了要执行的下一条指令位置
irytu
2023-05-25 06:02:50 +08:00
不被调度的状态
irytu
2023-05-25 06:03:53 +08:00
@xausky yield 就是让出 CPU 时间 给其他任务
thezhang98
2023-05-25 09:54:38 +08:00

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/942365

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX