Possible bug with `ThreadLocal.asContextElement`

Hello,
I’m observing a strange behavior with the following code:

	val t: ThreadLocal<String> = ThreadLocal.withInitial { "a" }

	@Test
	fun testContext1() = runBlocking {
		println(t.get())
		withContext(coroutineContext.plus(t.asContextElement("b"))) {
			println(t.get())
		}
		println(t.get())
	}

	@Test
	fun testContext2() = runBlocking {
		println(t.get())
		withContext(coroutineContext.plus(t.asContextElement("b"))) {
			println(t.get())
			delay(Random.nextLong(100))
			println(t.get())
		}
		println(t.get())
	}

	@Test
	fun testContext3() = runBlocking {
		println(t.get())
		async(coroutineContext.plus(t.asContextElement("b"))) {
			println(t.get())
			delay(Random.nextLong(100))
			println(t.get())
		}.await()
		println(t.get())
	}

The result is:

  • testContext1 prints aba (expected)
  • testContext2 prints abbb. It looks like the value is not restored for some reason. Is this a bug? What’s the explanation?
  • testContext3 prints abba (expected)

Please help!

I submitted as Github issue: Possible bug with `ThreadLocal.asContextElement` · Issue #985 · Kotlin/kotlinx.coroutines · GitHub

1 Like