Gala Bill
01/29/2025, 3:20 PMactor
but that seems to be obsolete .
Also using cancelAndJoin() for a previos job before starting a new one doesn't guarantee that only one coroutine will run. For example in the following code even though I used cancelAndJoin two coroutines run concurrently
var job: Job? = null
suspend fun foo(id: String) {
println("START $id")
Thread.sleep(500)
yield()
println("DONE $id")
}
fun main(): Unit = runBlocking {
launch {
println("Launch1")
job?.cancelAndJoin()
println("StartJob1")
job = launch {
foo("1")
}
}
launch {
println("Launch2")
job!!.cancelAndJoin()
println("StartJob2")
job = launch {
foo("2")
}
}
launch {
println("Launch3")
job!!.cancelAndJoin()
println("StartJob3")
job = launch {
foo("3")
}
}
}
//OUTPUT
Launch1
StartJob1
Launch2
Launch3
StartJob2
StartJob3
START 2
START 3
DONE 2
DONE 3
streetsofboston
01/29/2025, 3:23 PMfoo("1"); foo("2"); ...
If you want to make it re-entrant, use a Mutex, which can guard against re-entry from another threadstreetsofboston
01/29/2025, 3:24 PMGala Bill
01/29/2025, 3:32 PMstreetsofboston
01/29/2025, 3:33 PMmichaelsims
01/29/2025, 3:35 PMMutex has two states: locked and unlocked. It is non-reentrant, that is invoking lock even from the same thread/coroutine that currently holds the lock still suspends the invoker.
Gala Bill
01/29/2025, 3:36 PMYoussef Shoaib [MOD]
01/29/2025, 5:37 PMAbhishek Tyagi
01/29/2025, 7:04 PMThread.sleep()
is not cooperative hence your job will not be cancelled, use delay()
instead.