How does `kotlinx.coroutines.sync.Mutex` provides ...
# coroutines
a
How does
kotlinx.coroutines.sync.Mutex
provides `cache visibility`/`happen before` guarantees? 🤔 It looks like optimistic path works via `atomic`(compare-and-set) permits. Consider case when Dispatcher has multiple threads: 0. mutex unlocked 1.
Coroutine A
from
Thread A
on
CPU Core A
increments counter (optimistic path via atomics) 2. mutex unlocked 3.
Coroutine B
from
Thread B
on
CPU Core B
increments counter (optimistic path via atomics) I understand why it works when
mutex
is locked (cas fails) so
coroutine
suspends, then(eventually)
resume
happens which involves some task to be scheduled to Dispatcher i.e. interaction with smth like `LinkedBlockingQueue`(put() and take() provides
happens before
). What forces
counter
value to be synced across cores? if in both cases
only atomics
were involved? Maybe that's not true and some other synchronization also happens that I'm not aware of.
Code:
Copy code
var counter = 0
    val mutex = Mutex()

    runBlocking {
        repeat(1_000_000) {
            scope.launch {
                withContext(Dispatchers.IO) {
                    mutex.withLock {
                        counter++
                    }
                }
            }
        }

        scope.coroutineContext.job.children.forEach { it.join() }
    }

    println("Counter: $counter")
d
Atomic variables guarantee happens-before: https://stackoverflow.com/a/44191608.
weakCompareAndSet
is the version of
compareAndSet
without the happens-before guarantees.
👍 1