From 454ec5d477e92b79bd3bdc5d1c31c1092e6bcc0e Mon Sep 17 00:00:00 2001 From: Harald Gutsche Date: Tue, 16 May 2023 22:43:06 +0200 Subject: [PATCH] add coroutine/synchronized test --- .../kotlin/research/Try_concurrent.kt | 102 ++++++++++++++---- 1 file changed, 80 insertions(+), 22 deletions(-) diff --git a/app/src/androidTest/kotlin/research/Try_concurrent.kt b/app/src/androidTest/kotlin/research/Try_concurrent.kt index 8e6f48e6c9..fd68fd3166 100644 --- a/app/src/androidTest/kotlin/research/Try_concurrent.kt +++ b/app/src/androidTest/kotlin/research/Try_concurrent.kt @@ -1,6 +1,9 @@ package research -import kotlinx.coroutines.* +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock import org.junit.Assert.assertEquals @@ -9,12 +12,14 @@ import kotlin.system.measureTimeMillis class Try_concurrent { - val n = 10 // number of coroutines to launch - val t = 100L // times an action is repeated by each coroutine + val n = 10 // number of jobs to launch + val t = 100L // time to wait in each coroutine - suspend fun massiveCoroutines(action: suspend () -> Unit) { + private var theMap = mutableMapOf() + + fun massiveCoroutines(dispatcher: CoroutineDispatcher, action: suspend () -> Unit) { val time = measureTimeMillis { - coroutineScope { // scope for coroutines + runBlocking(dispatcher) { repeat(n) { launch { action() @@ -22,13 +27,13 @@ class Try_concurrent { } } } - println("Completed $n actions in $time ms") + println("----------> Completed actions in $n coroutines in $time ms") } fun massiveThreads(action: () -> Unit) { val jobs = mutableListOf() val time = measureTimeMillis { - repeat(n) { + repeat(n) { index -> jobs.add( Thread { action() @@ -37,40 +42,93 @@ class Try_concurrent { } jobs.forEach { it.join() } } - println("Completed $n actions in $time ms") + println("----------> Completed actions in $n threads in $time ms") + } + + fun theAction() { + val x = counter + //theMap[x] = (theMap[x] ?: 0) + 1 + Thread.sleep(t) + counter = x+1 + } + + fun theAssertions() { + assertEquals(n, counter) + //repeat(n) { + // assertEquals(1, theMap[it]) + //} } var mutex = Mutex() + object lock var counter = 0 @Test - fun test_coroutine_withLock() = runBlocking { + fun test_coroutine_withLock(){ counter = 0 - withContext(Dispatchers.Default) { - massiveCoroutines { - // protect each increment + massiveCoroutines(Dispatchers.Default) { mutex.withLock { - val x = counter - delay(1000) - counter = x+1 - } + theAction() + } + } + assertEquals(n, counter) + } + + @Test + fun test_coroutine_io_withLock() { + counter = 0 + massiveCoroutines(Dispatchers.IO) { + mutex.withLock { + theAction() } } assertEquals(n, counter) } @Test - fun test_thread_synchronized() = runBlocking { + fun test_thread_withLock() { counter = 0 massiveThreads { - // protect each increment - synchronized(counter) { - val x = counter - Thread.sleep(t) - counter = x+1 + runBlocking { + mutex.withLock { + theAction() + } } } assertEquals(n, counter) } + @Test + fun test_thread_synchronized(){ + counter = 0 + massiveThreads { + synchronized(lock) { + theAction() + } + } + theAssertions() + } + + @Test + fun test_coroutine_synchronized(){ + counter = 0 + massiveCoroutines(Dispatchers.Default) { + synchronized(lock) { + theAction() + } + } + theAssertions() + } + + @Test + fun test_coroutine_io_synchronized(){ + counter = 0 + massiveCoroutines(Dispatchers.IO) { + synchronized(lock) { + theAction() + } + } + theAssertions() + } + }