Luis Munoz
08/01/2019, 8:25 PMgroostav
08/01/2019, 8:26 PMupdate()
Luis Munoz
08/01/2019, 8:26 PMLuis Munoz
08/01/2019, 8:27 PMLuis Munoz
08/01/2019, 8:27 PMDominaezzz
08/01/2019, 8:27 PMMutex
or AtomicInt .groostav
08/01/2019, 8:28 PMclass Example : CoroutineScope {
//extending coroutine scope doesnt get you anything implicitly. It does make `launch()` and `async` et all easier to use
val mutex = Mutex()
suspend fun update() {
mutex.withLock {
count++
}
}
}
Luis Munoz
08/01/2019, 8:28 PMgroostav
08/01/2019, 8:28 PMDispatchers.Main
, Dispatchers.JavaFx
, etc)
suspend fun update() = withContext(this.coroutineContext){
count++
}
Luis Munoz
08/01/2019, 8:29 PMgroostav
08/01/2019, 8:30 PMLuis Munoz
08/01/2019, 8:31 PMDominaezzz
08/01/2019, 8:31 PMgroostav
08/01/2019, 8:31 PMDispatchers.Default
will give you highly parallel behaviour by default. If thats part of your context you will find it running in parallel on many different threads.
I will say that koltin coroutines typically offer sqeuential concurrent behaviour by default. This is easier to leverage if you avoid state machiens (eg update()
) instead favouring channels.groostav
08/01/2019, 8:34 PMLuis Munoz
08/01/2019, 8:34 PMgroostav
08/01/2019, 8:35 PMmutex.withLock { mutex.withLock {}}
will deadlockLuis Munoz
08/01/2019, 8:38 PMgroostav
08/01/2019, 8:40 PMExecutors.newSingelThreadedExecutor().asCoroutineDispatcher()
in your scope's context and then withContext
--ing every entry point will give you single-threaded concurrency, which might be helpful.Luis Munoz
08/01/2019, 8:43 PMLuis Munoz
08/01/2019, 8:44 PMDominaezzz
08/01/2019, 8:45 PMDominaezzz
08/01/2019, 8:45 PMDominaezzz
08/01/2019, 8:45 PMLuis Munoz
08/01/2019, 8:49 PMgroostav
08/01/2019, 8:50 PMDominaezzz
08/01/2019, 8:51 PMLuis Munoz
08/01/2019, 8:57 PMDominaezzz
08/01/2019, 8:59 PMgroostav
08/01/2019, 11:32 PMExecutors
, such that rather than have Executors.newSingleThreadedExecutor
and Executors.forkJoinPool
you would have Executors.make(context = SingleThreaded)
. You can absolutely take a coroutine context and re-use it by doing
val context = EmptyCoroutineContext + MySpecialContext
GlobalScope.launch(context) { /* job1 */ }
GlobalScope.launch(context) { /* job2 */ }
In this way, both job1 and job2 have the same context.
The purpose of scope (as opposed to context) is mostly to try and employ a parent-child relationship to try and keep management a little easier and error states a little cleaner.Luis Munoz
08/07/2019, 7:52 PMLuis Munoz
08/07/2019, 7:52 PMLuis Munoz
08/07/2019, 7:52 PMDominaezzz
08/07/2019, 8:27 PMDominaezzz
08/07/2019, 8:29 PMgroostav
08/07/2019, 11:58 PMlaunch
does indeed give you a new coroutine context with a new (parent) job in it. Context
is a key value store. The implementation of parent-child'ing in jobs relies on a mutable Job
implementation. To my knowledge all other coroutine context elements are either stateless or immutable.groostav
08/08/2019, 12:04 AMsuspend fun
method there is nothing in a coroutine's context that will help you directly. You can get single-threaded behaviour by changing Dispatchers
. You can use mutex
to acquire a lock --you could even put it in your coroutine context to make it a reentrant lock.