https://kotlinlang.org logo
#coroutines
Title
# coroutines
s

SecretX

02/26/2021, 6:56 AM
(DefaultDispatcher-worker-5 @coroutine#5) Subscribing 10000 listeners took 177ms
(DefaultDispatcher-worker-4 @coroutine#4) Subscribing 10000 listeners took 178ms
(DefaultDispatcher-worker-1 @coroutine#3) Subscribing 10000 listeners took 178ms
(DefaultDispatcher-worker-3 @coroutine#2) Subscribing 10000 listeners took 178ms
(DefaultDispatcher-worker-6 @coroutine#6) Subscribing 10000 listeners took 178ms
(main @coroutine#1) Unsubscribing all 49962 listeners took 0ms
u

uli

02/26/2021, 7:09 AM
Could it be due to extension functions being used on MutableMap/Collection instead of some concurrent implementations?
Check!
contains
is a kotlin extension on maps which inlines to
containsKey
And it is also a member on
ConcurrentHashMap
which calls ….
contanisValue
So your ConcurrentHashMap version is simply wrong 😉
could you check timing on both versions with
containsKey
instead of
contains
As a side note, this code races between multiple threads and is not protected by the guarantees of `ConcurrentHashMap`:
Copy code
while(observers.contains(uuid)) {
            Thread.sleep(1)
            uuid = UUID.randomUUID()
        }
You should probably use
putIfAbsent
Untested example:
Copy code
fun addListener(observer: Observer<T>): Subscription<T> {
        var uuid = UUID.randomUUID()
        while (observers.putIfAbsent(uuid, observer) != null) {
            Thread.sleep(1)
            uuid = UUID.randomUUID()
        }
        val subscription = Subscription(uuid, this)
        return subscription
    }
s

SecretX

02/27/2021, 7:25 PM
When I changed the contain to containKey, both MutableMap and ConcurrentHashMap performed the same, thank you. Also, your untested example worked just fine, I'm going with it, thank you! @uli
👍 2
u

uli

03/01/2021, 8:50 AM
Do you still need the
Thread.sleep(1)
? Or was that to avoid races?
4 Views