Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin coroutine concurrency and cached value

I'm currently trying to create a caching layer around a web request. So far I've written:

class Repository(private val webServices: WebServices) {
  private var cachedItems: List<Item>? = null

  suspend fun getItems(): List<Item> {
    cachedItems?.let { return it }

    val items = withContext(Dispatchers.IO) { webServices.getItems() }
    cachedItems = items
    return items
  }
}

My concern is what will happen when getItems() is invoked by two callers simultaneously. Ideally, I'd only want one web request to occur. What's the recommended approach for dealing with this issue when using coroutines?

like image 377
Chris Horner Avatar asked Sep 19 '19 09:09

Chris Horner


People also ask

Are Kotlin coroutines concurrent?

Kotlin coroutines & structured concurrency In Kotlin, we can create coroutines using builders such as launch and async , which return a Job instance. This Job may further contain nested coroutine builders that create children Job instances that are computed concurrently.

Is coroutine concurrent?

coroutines library provides support for using multiple threads. It is a separate branch for the reasons listed in the future concurrency model blog post. However, you can still use the multithreaded version of kotlinx.

Are Kotlin coroutines thread safe?

Channel class kotlinx. coroutines library is thread-safe. It is designed to support multiple threads.

Why are coroutines cheaper than threads?

Similar to threads, coroutines can run in concurrently, wait for, and communicate with each other with the difference that creating them is way cheaper than threads.


1 Answers

Here's a simple solution.

class Repository(private val webServices: WebServices) {
  private val cachedItems = async(Dispatchers.IO, start = CoroutineStart.LAZY) {
    webServices.getItems()
  }

  suspend fun getItems(): List<Item> {
    return cachedItems.await()
  }
}
like image 179
Dominic Fischer Avatar answered Sep 30 '22 01:09

Dominic Fischer