当前位置: 首页 > news >正文

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

http://www.dtcms.com/a/414323.html

相关文章:

  • 【MySQL✨】MySQL 入门之旅 · 第十篇:数据库备份与恢复
  • k8s里三种探针的使用场景
  • 8.基于 Ingress-nginx-controller 实现 k8s 七层代理
  • Kling-Audio-Eval - 高质量视频到音频生成评估数据集
  • LeetCode 812.最大三角形的面积
  • 做网站都需要服务器吗域名类型
  • js逆向实战:爬取淘宝男装商品
  • 前端3.0
  • 机器视觉检测中,最小尺寸多少像素可以检测到?重点解析传统算法和深度学习,对比度很致命
  • 不同浏览器中高效维护需要登录网站的登录态
  • 【C++list】底层结构、迭代器核心原理与常用接口实现全解析
  • socket编程 netstat 大小端 rpc 协程 io yield
  • 网站建设与维护百度百科自己做app的软件
  • 制作公司网站要多少费用呢二手书交易网站策划书
  • 【vue3】watch、watchEffect、watchPostEffect和watchSyncEffect的区别详解
  • 【仿生机器人】核心采购清单 (仿生机器人头项目)
  • 云服务器 + Jenkins 实现项目自动化部署与上线
  • wordpress调用当前年份的7种方式
  • 通用性AI大模型辅助本科机器人课程完成编程项目的可靠性分析
  • 使用 EMQX 社区版 v5.8.7 将 MQTT 消息持久化到 MySQL 数据库的实践指南
  • MATLAB中的Excel文件操作:从入门到精通
  • SpringMVC 入门:核心概念与第一个 HelloWorld 案例
  • 山东省建设厅继续教育网站网站做商标在那类
  • 【Linux网络】Socket编程:UDP网络编程实现DictServer
  • 虚拟空间可以做视频网站么删除重装wordpress
  • 【Agent】在基于WSL2的Linux的ALSA输出音频
  • LeetCode:68.寻找两个正序数组的中位数
  • 在 Unity 中使用 SoundTouch 插件控制音频倍速播放
  • 通过keepalived搭建MySQL双主模式的MySQL集群
  • MySQL压缩表创建指南