^ this inspired me to test whether switching threa...
# coroutines
m
^ this inspired me to test whether switching threads in a coroutine flushes the cache similarly to java
synchonized
block. Here's the test, results in thread
Copy code
import kotlinx.coroutines.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.yield

class Test {
    var i = 0

    suspend fun countWithThreadSwitching(){
        repeat(10) {
            i++
            delay(1) //yield() didn't make coroutine resume on another thread
        }
        println(i)
    }
}

fun main() = runBlocking {
    coroutineScope{
        repeat(100) {
            launch(Dispatchers.Default) {
                Test().countWithThreadSwitching()
            }
        }    
    }
}
Looks like it does - it writes out 100x 10
d
cache?
m
CPU cache
It does flush the cache
d
L1? How do you know?
d
It's not even switching threads
j
Yea the above isn’t switching threads.. did you mean something like this?
Copy code
@Test
    fun main() = runBlocking {
        repeat(100) {
            val t = Test()
            coroutineScope {
                launch(Dispatchers.Default) {
                    t.countWithThreadSwitching()
                }
            }
            println(t.i) 
        }
    }
m
^ that makes coroutines execute sequentially, no parallelism at all
I wanted to have mutable state changed on only one coroutine which would switch threads
I was expecting
yield
to release current thread and another thread from pool to pick up the coroutine for execution later
Using
delay(1)
instead of
yield()
did the trick
d
So I don't think the code working as expected says much about cpu cache
You're changing a variable from one thread at a time
m
Yeah but some thread could have that variable cached and not notice another thread incrementing the value. In that case some output would be <10
Either caches are flushed on thread switch or I need a better code to cause the scenario
d
Caches are always flushed in general, regardless of Kotlin, JVM or OS. CPU guarantees.
m
In that case, there wouldn't be a need for AtomicInt, right?
or
volatile
d
Race conditions are still a thing with cache flushed.
Depending on the language,
volatile
just tells the compiler to take it easy with the optimizations.
For example the compiler might cache the variable in a register but that won't work for multithreading.
m
Ok, one clarification, by cache flushing I also meant cache invalidation
I didn't find proper term for cache flushing+invalidation
So, before entering java's
synchronized
block, caches are invalidated and before leaving it, caches are flushed (ok, that part is CPU automatic)
I was interested whether thread switches in coroutines do the same, that's what code is trying to test
d
Since the variable in stored in the heap and captured all over the place, compiler will be very hesitant to optimise the variable away.
So there will be no (Language level) caching in the first place.