diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/SnapshotStateObserver.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/SnapshotStateObserver.kt index aec9166f8b32d..8affa829be594 100644 --- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/SnapshotStateObserver.kt +++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/SnapshotStateObserver.kt @@ -53,7 +53,9 @@ class SnapshotStateObserver(private val onChangedExecutor: (callback: () -> Unit */ private val readObserver: (Any) -> Unit = { state -> if (!isPaused) { - currentMap!!.addValue(state) + synchronized(applyMaps) { + currentMap!!.addValue(state) + } } } diff --git a/compose/runtime/runtime/src/test/kotlin/androidx/compose/runtime/snapshots/SnapshotStateObserverTests.kt b/compose/runtime/runtime/src/test/kotlin/androidx/compose/runtime/snapshots/SnapshotStateObserverTests.kt index 66b607b9a9546..af482386b69ed 100644 --- a/compose/runtime/runtime/src/test/kotlin/androidx/compose/runtime/snapshots/SnapshotStateObserverTests.kt +++ b/compose/runtime/runtime/src/test/kotlin/androidx/compose/runtime/snapshots/SnapshotStateObserverTests.kt @@ -324,6 +324,44 @@ class SnapshotStateObserverTests { assertNull(threadException) } + @Test // regression test for 192677711, second case + fun tryToReproduceSecondRaceCondtion() { + var running = true + var threadException: Exception? = null + try { + thread { + try { + while (running) { + Snapshot.sendApplyNotifications() + } + } catch (e: Exception) { + threadException = e + } + } + + for (i in 1..10000) { + val state1 by mutableStateOf(0) + var state2 by mutableStateOf(true) + val observer = SnapshotStateObserver({}).apply { + start() + } + observer.observeReads(Unit, {}) { + repeat(1000) { + @Suppress("UNUSED_EXPRESSION") + state1 + if (state2) { + state2 = false + } + } + } + assertNull(threadException) + } + } finally { + running = false + } + assertNull(threadException) + } + private fun runSimpleTest( block: (modelObserver: SnapshotStateObserver, data: MutableState) -> Unit ) {