Kotlin轻量级互斥锁Mutext与轻量级信号量Semaphore异同比较
Kotlin轻量级互斥锁Mutext与轻量级信号量Semaphore异同比较
Semaphore信号量
Semaphore是计数器,限制对某些资源的访问数量。
Semaphore内部维护一个计数器,当一个线程获得资源时,计数器减一;当线程释放资源时,计数器加一。当计数器为零时,其他尝试获取资源的线程将被阻塞,直到有线程释放资源,计数器大于零。
使用场景:Semaphore通常在并发环境中控制对一组资源的并发访问数量,例如数据库连接池、线程池,网络请求数量等。
Mutex互斥锁
Mutex用于保护单个资源,确保在并发环境中,同一时间只有1个线程可以访问该资源。Mutex通常用于保护区域的互斥访问。
Mutex有两种状态:锁定和未锁定。当一个线程尝试获取Mutex时,如果Mutex处于未锁定状态,线程将获得Mutex并继续执行;如果Mutex已被其他线程锁定,该线程将被阻塞,直到Mutex被释放。
使用场景:Mutex通常用于保护对单个共享资源的访问,例如文件、某个特定变量等。
总结
Semaphore用于保护一组资源的访问,Mutex用于保护一个资源。
提醒:Mutex实现相对简单,且仅控制单一资源,在性能上,其表现可能优于Semaphore。
特别注意死锁
在使用Semaphore时,不恰当的使用,可能会导致死锁。例如,多个线程互相等待对方释放资源,可能导致所有线程都无法继续执行。使用Semaphore时,确保线程之间的依赖关系中不会导致死锁。一种常见的方法是遵循固定的资源访问顺序。
确保在适当的时候释放Mutex或Semaphore,避免资源泄露和线程阻塞。
合理选择
如果需要保护一组资源或限制并发访问的数量,使用Semaphore;如果只是需要保护单个资源,使用Mutex。
最佳实践
Mutex是一种互斥锁,不可重入,可以使用withLock函数加锁并执行临界区代码块。
Semaphore是一种计数信号量,可以使用withPermit函数控制并发访问资源的线程数量。
package org.exampleimport kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.Semaphore
import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.sync.withPermitfun main() = runBlocking {val A = "a"val B = "b"val C = "c"val repeatCnt = 3val semaphore = Semaphore(1)//Semaphore信号量协程同步semaphoreTask(semaphore, A, repeatCnt)semaphoreTask(semaphore, B, repeatCnt)semaphoreTask(semaphore, C, repeatCnt)delay(60)println("#####")val mutex = Mutex()//Mutex互斥锁协程同步mutexTask(mutex, A, repeatCnt)mutexTask(mutex, B, repeatCnt)mutexTask(mutex, C, repeatCnt)delay(60)
}private fun semaphoreTask(semaphore: Semaphore, tag: String, repeatCnt: Int) {CoroutineScope(Dispatchers.IO).launch {semaphore.withPermit {print(repeatCnt, tag)}}
}private fun mutexTask(mutex: Mutex, tag: String, repeatCnt: Int) {CoroutineScope(Dispatchers.IO).launch {mutex.withLock {print(repeatCnt, tag)}}
}private fun print(repeatCnt: Int, tag: String) {repeat(repeatCnt) { it ->val d = (Math.random() * 10).toLong()Thread.sleep(d)println("$tag-$it $d ${System.currentTimeMillis()}")}
}
a-0 1 1758681134542
a-1 4 1758681134546
a-2 4 1758681134550
b-0 8 1758681134564
b-1 3 1758681134568
b-2 6 1758681134574
c-0 0 1758681134574
c-1 9 1758681134584
c-2 1 1758681134587
#####
a-0 3 1758681134620
a-1 2 1758681134624
a-2 3 1758681134629
c-0 7 1758681134638
c-1 1 1758681134640
c-2 0 1758681134640
b-0 6 1758681134647
b-1 6 1758681134655
b-2 0 1758681134655
相关:
Kotlin互斥锁Mutex协程withLock实现同步: https://blog.csdn.net/zhangphil/article/details/151973525