对 Kotlin 与协程相关的挂起函数感到困惑
Confused about Kotlin's suspending functions in relation to coroutines
如果我理解正确,挂起函数是您可以在协程内执行的函数,挂起函数的作用是挂起协程,以便另一个协程可以开始工作。现在,这是否意味着协程挂起时挂起函数仍在工作?这就是让我感到困惑的地方,因为我看到很多文本都说它不仅会暂停协程,还会暂停暂停功能。但是,如果它也暂停了暂停功能,那么暂停您想要完成的工作有什么意义呢?
假设我有一个暂停函数需要 30 秒才能完成一些数学计算。然后我有另一个协程,它说打印了一些简单的文本,比如 "Hello, World"。如果第一个协程挂起,去第二个协程打印问候语,数学计算还会同时进行吗?
Now, does this mean that while the coroutine is suspended that the suspend function is still doing work?
不,但是 withContext
原语可能会让您感到困惑,它使您的函数 运行 在当前协程挂起时在另一个线程上运行。这样,您的函数 运行ning 在后台线程上,而其他协程 运行ning 在主线程上并发。
This is what confuses me because I've seen many texts say that it pauses not only the coroutine but also the suspend function.
这是正确的。
But if it pauses the suspend function as well then whats the point if the work you wanted to be done is paused?
主要用例是将工作委托给外部资源,尤其是网络层。当您的函数正在等待来自网络的数据时,它无事可做。与此同时,其他协程可能会继续在同一个线程上执行。
Suppose I had a suspend function that takes 30 seconds to finish doing some mathematical calculation.
该函数即使声明为可暂停,实际上也不会自行暂停。它会一直占用调用线程。
And then I had another coroutine that said printed some simple text like "Hello, World".
如果您使用的是单线程调度程序,则该协程必须等待轮到它,直到第一个协程明确挂起自身,这在您提到的 CPU 密集型函数中可能不会发生。
If the first coroutine suspends and goes to the second coroutine to print the greeting, would mathematical calculation still be happening at the same time?
如上所述,如果您使用 withContext
,计算和打印将同时 运行,但这只是因为涉及到另一个线程。
第一个协程也可以在其计算循环中调用 yield()
,从而允许 Kotlin 暂停它和 运行 同一线程上的其他一些协程。在这种情况下,暂停时不会取得任何进展。
您可以这样看:假设有一个线程 运行连接所有协程。他们将 运行 的方式称为 合作并发 。协程必须显式挂起自己以允许其他人运行。这与在单个 CPU 内核上并发 运行 多个线程非常相似,只是 OS 可以再做一件 "magical" 事情:它可以随时挂起线程时间,未经该线程的许可。这就是为什么这种被称为 pre-emptive concurrency.
如果我理解正确,挂起函数是您可以在协程内执行的函数,挂起函数的作用是挂起协程,以便另一个协程可以开始工作。现在,这是否意味着协程挂起时挂起函数仍在工作?这就是让我感到困惑的地方,因为我看到很多文本都说它不仅会暂停协程,还会暂停暂停功能。但是,如果它也暂停了暂停功能,那么暂停您想要完成的工作有什么意义呢?
假设我有一个暂停函数需要 30 秒才能完成一些数学计算。然后我有另一个协程,它说打印了一些简单的文本,比如 "Hello, World"。如果第一个协程挂起,去第二个协程打印问候语,数学计算还会同时进行吗?
Now, does this mean that while the coroutine is suspended that the suspend function is still doing work?
不,但是 withContext
原语可能会让您感到困惑,它使您的函数 运行 在当前协程挂起时在另一个线程上运行。这样,您的函数 运行ning 在后台线程上,而其他协程 运行ning 在主线程上并发。
This is what confuses me because I've seen many texts say that it pauses not only the coroutine but also the suspend function.
这是正确的。
But if it pauses the suspend function as well then whats the point if the work you wanted to be done is paused?
主要用例是将工作委托给外部资源,尤其是网络层。当您的函数正在等待来自网络的数据时,它无事可做。与此同时,其他协程可能会继续在同一个线程上执行。
Suppose I had a suspend function that takes 30 seconds to finish doing some mathematical calculation.
该函数即使声明为可暂停,实际上也不会自行暂停。它会一直占用调用线程。
And then I had another coroutine that said printed some simple text like "Hello, World".
如果您使用的是单线程调度程序,则该协程必须等待轮到它,直到第一个协程明确挂起自身,这在您提到的 CPU 密集型函数中可能不会发生。
If the first coroutine suspends and goes to the second coroutine to print the greeting, would mathematical calculation still be happening at the same time?
如上所述,如果您使用 withContext
,计算和打印将同时 运行,但这只是因为涉及到另一个线程。
第一个协程也可以在其计算循环中调用 yield()
,从而允许 Kotlin 暂停它和 运行 同一线程上的其他一些协程。在这种情况下,暂停时不会取得任何进展。
您可以这样看:假设有一个线程 运行连接所有协程。他们将 运行 的方式称为 合作并发 。协程必须显式挂起自己以允许其他人运行。这与在单个 CPU 内核上并发 运行 多个线程非常相似,只是 OS 可以再做一件 "magical" 事情:它可以随时挂起线程时间,未经该线程的许可。这就是为什么这种被称为 pre-emptive concurrency.