线程管理互斥与同步

时间:2021-05-13 10:50:15

标签: android multithreading kotlin global-scope

我有几个选择:

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)
        }
}

输出:

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)
        }
    }

输出:

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)
        }
     }

输出:

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)
        }
    }

输出:

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

我的问题是:

  1. 是什么导致 A 和 D 的行为不同? GlobalScope 是否有更多线程,而 LifecycleScope 是否只有单线程?
  2. B、C、D 的行为方式相同,但我对 Mutex 的假设是它阻止对线程的访问并且从不调用该函数。所以同步可以以同步方式运行它。那么互斥锁与同步有什么不同呢?
  3. lifecycleScope 在某些方面是否与同步相同?

1 个答案:

答案 0 :(得分:2)

您的问题的答案是:-

  1. lifecycleScope.launch 不会在单独的线程中运行代码,默认情况下它将使用 Main Dispatcher,如果您希望它在单独的线程中运行,您可以传递一个 Dispatcher,如 {{1} } 另一方面, lifecycleScope.launch(Dispatchers.IO) 将默认使用 GlobalScope 。您可以通过在 Dispatchers.Default 中打印线程名称来检查这一点。

  2. 在这种情况下,launchMutex 是相同的,因为您在整个执行过程中都持有互斥体,只有在线程完成其代码运行后,它才会被释放。 @Synchronized 将使方法本身 @Synchronized 的行为相同。

  3. synchronized 只是一个作用域,与 lifecycleScope 无关。

这些是对您问题的叙述性较少的答案,我希望它有意义。您可以通过在 synchronized 内的 Log 中打印线程名称来检查这些行为。 请查看This nice answer以获得更深入的理解。