协程进阶:上下文 11. 线程局部变量与协程

本篇解析 example-context-11.kt。探讨如何解决协程切换带来的线程局部变量失效问题。

1. 核心概念:asContextElement

由于协程会跨线程执行,直接使用 ThreadLocal 无法保证在协程恢复后依然能拿到之前设置的数据。

解决方案:

  • **asContextElement()**:将 ThreadLocal 变量包装为协程上下文。
  • 特性:每当协程恢复执行时,它会自动从上下文中取出对应的值,重新设置到当前线程的 ThreadLocal 中。

2. 代码解析

1
2
3
4
5
6
7
8
9
10
11
val threadLocal = ThreadLocal<String?>()

fun main() = runBlocking {
threadLocal.set("main")
// 通过 asContextElement 传递数据给子协程
val job = launch(Dispatchers.Default + threadLocal.asContextElement(value = "launch")) {
println(threadLocal.get()) // 拿到 "launch"
yield()
println(threadLocal.get()) // 挂起后恢复,依然拿到 "launch"
}
}

3. 开发者感悟

asContextElement 是连接“旧世界”(基于 ThreadLocal 的各种日志、事务管理等)与“新世界”(协程)的桥梁。在 Android 开发中,如果需要传递 TraceID 或全局状态,这种机制是不可或缺的。

,