Skip to content

Shared Mutable State doc #2304

Open
Open
@circusmagnus

Description

@circusmagnus

There is a section in coroutines guide "Shared mutable state and concurrency". Inside there is a statement, that accessing shared mutable state from multiple coroutines executed in a multithreaded Dispatcher is not safe. That is entirely correct. However accessing shared mutable state by multiple coroutines confined to a single thread (like Dispatchers.Main) is not really safe too.

Consider this example:

class SomeClass {
   var lastUsedUserId

   suspend fun loadUser(): User {
      if(lastUsedUserId != getCurrentUserId() ) {
         val newUser = callSuspendFun()
         lastUserId = newUser.id
         return newUser
      }
      else doSomethingElse()
   }
}

If fun loadUser() was a normal function && it was always called on same thread - this would be an ok code. We check whether user has changed, fetch its data and cache new user id for further invocations.
Now e.g. all default coroutineScopes on Android (viewmodelScope, livedataScope, etc) operate on Dispatchers.Main. So everything in this suspend fun should run on single, main thread, and should work, as if it were normal function, right?
No.
suspend fun loadUser() may... suspend. And in the meantime another, MainThread-bound coroutine may invoke this function again. And possibly finish faster than first invocation, messing up our userId caching policy. Or any other mutable state, shared between coroutines - whether they are bound to multiple threads or only single-threaded.

I would mention in a guide, that accessing mutable state shared between corotuines / suspend functions is generally dangerous, no matter whether we operate on multithreaded Dispatcher, or single-threaded.

Metadata

Metadata

Assignees

No one assigned

    Labels

    guideIssues with the coroutines guide on the website

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions