androidmultithreadingkotlinglobal-scope

Thread management Mutex vs Synchronized


I have couple of options:

A:

   GlobalScope.launch {
        countTo("A",5)
    }
    GlobalScope.launch {
        countTo("B",5)
    }

    
   private fun countTo(from:String, k: Int) {
        for (i in 0 until k) {
            RLog.d("From:$from: $i")
            Thread.sleep(1000)
        }
}

Output:

From:A: 0
From:B: 1
From:A: 1
From:B: 2
From:A: 2
From:B: 3
From:A: 3
From:B: 4
From:A: 4

B:

   GlobalScope.launch {
        countTo("A",5)
    }
    GlobalScope.launch {
        countTo("B",5)
    }

   private val lock = Mutex()
   private suspend fun countTo(from:String, k: Int) {
    lock.withLock {
        for (i in 0 until k) {
            RLog.d("From:$from: $i")
            Thread.sleep(1000)
        }
    }

Output:

From:A: 0
From:A: 1
From:A: 2
From:A: 3
From:A: 4
From:B: 0
From:B: 1
From:B: 2
From:B: 3
From:B: 4

C:

    GlobalScope.launch {
        countTo("A",5)
    }
    GlobalScope.launch {
        countTo("B",5)
    }

    @Synchronized
    private fun countTo(from:String, k: Int) {
        for (i in 0 until k) {
            RLog.d("From:$from: $i")
            Thread.sleep(1000)
        }
     }

Output:

From:A: 0
From:A: 1
From:A: 2
From:A: 3
From:A: 4
From:B: 0
From:B: 1
From:B: 2
From:B: 3
From:B: 4

D:

    lifecycleScope.launch {
        countTo("A",5)
    }
    lifecycleScope.launch {
        countTo("B",5)
    }

    private fun countTo(from:String, k: Int) {
        for (i in 0 until k) {
            RLog.d("From:$from: $i")
            Thread.sleep(1000)
        }
    }

Output:

From:A: 0
From:A: 1
From:A: 2
From:A: 3
From:A: 4
From:B: 0
From:B: 1
From:B: 2
From:B: 3
From:B: 4

My questions is:

  1. What causes A and D act differently? Does GlobalScope have more threads and lifecycleScope have single thread?
  2. B,C,D acts the same way, but my assumption of Mutex was it block access to thread and never calls the function. So synchronized can run it in sync way. So what mutex different from synchronized?
  3. Does lifecycleScope acts same as synchronized in some way?

Solution

  • Answers to your question is :-

    1. lifecycleScope.launch does not run the code in separate thread it will use the Main Dispatcher by default, If you want it run in separate thread you can pass a Dispatcher like lifecycleScope.launch(Dispatchers.IO) On Other hand GlobalScope will by default use Dispatchers.Default . You can check this just printing the Thread name inside launch.

    2. In this case Mutex and @Synchronized is same because you are holding the mutext throughout the execution it will only get released once the thread done running its code. @Synchronized will make the method itself synchronized which will act the same.

    3. lifecycleScope is just a scope it has nothing to do with synchronized .

    These are the less narrative answers to your question i hope its making sense. You can check these behaviors by just printing the Thread name in Log inside launch. Please check This nice answer for a deeper understanding.