线程阻塞的真正含义是什么?结合Kotlin协程示例解析
问题解答
一、线程是否被阻塞?
线程没有被阻塞,核心原因是Kotlin协程的挂起机制:
当协程调用suspend fun delay()时,会主动将自身挂起,并立刻释放当前占用的线程(示例中的DefaultDispatcher-worker-1)。此时该线程完全可以去执行其他任务(比如其他协程、线程池内的其他工作),不会被闲置。
等delay(3000)的时间到期后,协程会被调度器重新分配到线程池中的某个线程(示例中刚好还是worker-1,但也可能是其他worker线程),继续执行后续代码。
你看到的日志顺序和同一线程标识,只是协程恢复后恰好被分配到了原线程,而非线程被阻塞了3秒无法处理其他任务。
二、同一线程上多协程的执行逻辑
你的理解完全正确,核心规则如下:
- 单个协程内部:代码串行执行
每个协程内的代码严格按顺序执行,比如第一个协程必须等doNetworkCall()执行完成(包括3秒delay),才会调用doNetworkCall2();第二个协程同理,doNetworkCall3()一定会在doNetworkCall4()之前执行。 - 不同协程之间:并发异步执行,无需互相等待
当第一个协程因delay挂起时,它占用的线程会被释放,此时线程可以立刻切换去执行第二个协程的代码。因此doNetworkCall1()和doNetworkCall3()的执行顺序完全不确定——可能先打印其中一个,也可能两个几乎同时输出(取决于调度器的调度时机),二者没有任何先后依赖关系。
举个典型的执行场景:
- 两个协程几乎同时启动,均进入
delay(3000)并挂起,释放线程; - 3秒后,两个协程同时被唤醒,进入线程池的任务队列;
- 线程池的worker线程(比如
worker-1)会从队列中依次取出任务执行,先执行哪个协程的恢复逻辑,就会先打印对应的日志。
内容的提问来源于stack exchange,提问作者HukeLau_DABA
相关产品推荐
相关产品推荐

