关键字:结构化并发、线程、Kotlin、协程
多线程的并发是全局的,而结构化并发中,每个并发都有自己作用域。
1. 线程的并发不是结构化的
可以想想这几个问题在 Java 中要怎么解决:
- 结束一个线程时,怎么同时结束这个线程中创建的子线程?
- 当某个子线程在执行时需要结束兄弟线程要做怎么做?
- 如何等待所有子线程都执行完了再结束父线程?
这些问题都可以通过共享标记位、CountDownLatch 等方式实现。但这两个例子让我们意识到,线程间没有级联关系;所有线程执行的上下文都是整个进程,多个线程的并发是相对整个进程的,而不是相对某一个父线程。
这就是线程的「非结构化」。
2. 业务的并发是结构化的
通常,每个并发操作都是在处理一个任务单元,这个任务单元可能属于某个父任务单元,同时它也可能有子任务单元。而每个任务单元都有自己的生命周期,子任务的生命周期理应继了父任务的生命周期。
这就是业务的「结构化」。
3. 结构化的并发应该是什么样?
在结构化的并发中,每个并发操作都有自己的作用域,并且:
在父作用域内新建作用域都属于它的子作用域;
父作用域和子作用域具有级联关系;
父作用域的生命周期持续到所有子作用域执行完;
当主动结束父作用域时,会级联结束它的各个子作用域。
例如 Kotlin 的协程就是 结构化的并发,它有 「协程作用域(CoroutineScope)」 的角色。全局的 GlobalScope 是一个作用域,每个协程自身也是一个作用域。新建的协程对象和父协程保持着级联关系。
可以看出 协程的并发 和 业务的并发 更相似,它们都具有结构上的关联。