trylock 用法_Java lock

trylock 用法_Java lock在并发编程中,为了避免多线程同时读写共享资源,我们需要互斥。Go标准库提供了互斥锁sync.Mutex,通过加锁Lock()方法和解锁Unlock()方法达到对共享资源的并发控制。在之前的设计中,当锁被占有,其他goroutine尝试获取锁时会被阻塞。这种方式当然是合理的,但是在某些情况下,或许我们希望在获取锁失败时,并不想停止执行,而是可以进入其他的逻…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

在并发编程中,为了避免多线程同时读写共享资源,我们需要互斥。Go 标准库提供了互斥锁 sync.Mutex ,通过加锁 Lock() 方法和解锁 Unlock() 方法达到对共享资源的并发控制。

在之前的设计中,当锁被占有,其他 goroutine 尝试获取锁时会被阻塞。这种方式当然是合理的,但是在某些情况下,或许我们希望在获取锁失败时,并不想停止执行,而是可以进入其他的逻辑。

在 Go 1.18 中,为 sync.Mutex 新增了一个新的方法 TryLock(),它是一种非阻塞模式的取锁操作。当调用 TryLock() 时,该函数仅简单地返回 true 或者 false,代表是否加锁成功。

有了 TryLock 的存在,我们就可以由这样的代码

m.Lock()
 // 阻塞等待加锁成功后的逻辑

转变成这样的逻辑

if m.TryLock(){
 // 加锁成功的逻辑
 }else {
 // 加锁失败的逻辑
 }

TryLock 实现

Go精妙的互斥锁设计一文中,我们详细分析过互斥锁的设计,其代码轻量简洁,通过巧妙的位运算,仅仅采用 state 一个字段就实现了四个字段的效果,非常之精彩,建议感兴趣的读者一读。

而 TryLock() 的实现更加简单

func (m *Mutex) TryLock() bool {
 old := m.state
 if old&(mutexLocked|mutexStarving) != 0 {
  return false
 }

 // There may be a goroutine waiting for the mutex, but we are
 // running now and can try to grab the mutex before that
 // goroutine wakes up.
 if !atomic.CompareAndSwapInt32(&m.state, old, old|mutexLocked) {
  return false
 }

 if race.Enabled {
  race.Acquire(unsafe.Pointer(m))
 }
 return true
}

当锁被其他 goroutine 占有,或者当前锁正处于饥饿模式,它将立即返回 false。

func (m *Mutex) Lock() {
 // Fast path: grab unlocked mutex.
 if atomic.CompareAndSwapInt32(&m.state, 0, mutexLocked) {
  if race.Enabled {
   race.Acquire(unsafe.Pointer(m))
  }
  return
 }
 // Slow path (outlined so that the fast path can be inlined)
 m.lockSlow()
}

而当锁可用时,TryLock() 会采用与 Lock() 方法一样的方式去尝试获取锁。但在获取失败时,与 Lock() 将不一样,它不会自旋或者阻塞。这是一个完全的非阻塞获取方式。

应用场景

正如 TryLock() 方法的注释一样,它的应用场景并不常见,并且也不被鼓励使用。

// Note that while correct uses of TryLock do exist, they are rare,
// and use of TryLock is often a sign of a deeper problem
// in a particular use of mutexes.

在当前 Go1.18 标准库源码中,与 Lock() 方法被大量内部使用而截然不同的是,并没有找到一处使用 TryLock() 的地方,仅仅在测试文件 mutex_test.go 中,有找到该方法的新增测试用例。

这里贴一个 TryLock 的使用场景讨论:https://stackoverflow.com/questions/41788074/use-case-for-lock-trylock

另外,在开源社区已经有不少 Go 的 TryLock 实现库。它们基于 sync.Mutex 通过 CAS 操作和 unsafe 指针实现 ;或者利用 channel 实现。

ad33d31b069a36af62811725c42834a6.png

但是这些库都不能竞态检测。因此,官方支持实现 TryLock 是必要的,避免 TryLock 被滥用。且由于可以集成竞态检测,相较于三方库实现,有利于开发者发现问题。

总结

从 2012 年开始,实际上很早就有关于 Go 增加 TryLock 的 issue 讨论,但是直到 Go 1.18 才被增加。这其中很大一部分原因是,并没有合理的案例值得添加 TryLock。

Go Team 的负责人 rsc 之前提出的反对意见:TryLock 会鼓励开发者对锁进行不精确的思考,并最终导致竞态问题。

另外,Go 1.18 除了为互斥锁 sync.Mutex 新增了 TryLoc() 方法外,也为读写锁 sync.RWMutex 新增了相应的 TryRLock() 和 TryLock() 方法。

正如新增的这三个方法的注释,虽然使用它们的情况存在,但很少见,使用需谨慎。

感谢你的点赞在看哦~

c383a04957f9ee7c74bf6b83d07be697.gif

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/183685.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 网络协议之视频直播核心技术讲解

    网络协议之视频直播核心技术讲解网络视频直播存在已有很长一段时间,随着移动上下行带宽提升及资费的下调,视频直播被赋予了更多娱乐和社交的属性,人们享受随时随地进行直播和观看,直播的打开时间和延迟变成了影响产品功能发展重要指标。那么,问题来了:如何实现低延迟、秒开的直播?先来看看视频直播的5个关键的流程:录制->编码->网络传输->解码->播放每个环节对于直播的延迟都会产生不同程度的影响。这里重点分析移动设备的情况。受限于技术的成熟度、硬件环境等,我们针对移动场景简单总结出直播延迟优化的4个点…

  • 将十进制转化为二进制的c语言程序_十进制111转换二进制

    将十进制转化为二进制的c语言程序_十进制111转换二进制目录十进制与二进制之间的转换十进制转换二进制C++实现十进制转换二进制二进制转换十进制C++实现二进制转换十进制十进制与二进制之间的转换十进制转换二进制十进制对2整除,得到的余数的倒序即为转换而成的二进制十进制转换二进制C++实现十进制转换二进制主函数main.cpp为:#include<iostream>#include<…

    2022年10月10日
  • 88hash 饰品交易平台 立刻取回的csgo开箱网站「建议收藏」

    88hash 饰品交易平台 立刻取回的csgo开箱网站「建议收藏」88hash饰品交易平台立刻取回的csgo开箱网站官方链接:www.88hash.com推广码:csgo(注册使用csgo随机赠送$0.5-$10刀)状态:有货直接取回,无货需要排队等待取回

  • tortoisegit 创建远程分支_git强制切换分支

    tortoisegit 创建远程分支_git强制切换分支公司项目GIT中有好几个分支,第一次使用提交错了,被教育了研究出来并记录一下使用TortoiseGit切换远程分支的方法第一步第二步

  • 51单片机实现流水灯

    51单片机实现流水灯文章目录51单片机实现流水灯一、点亮第一个LED灯二、流水灯1.总线型控制2.延时函数3._crol_函数使用4.实现流水灯51单片机实现流水灯以下是本篇文章正文内容,下面案例可供参考一、点亮第一个LED灯#include<reg52.h>#defineuintunsignedint//简化定义#defineucharunsignedchar//同上sbitD1=P2^1;voidmain(){ D1=0;}代码中D1代表着位定义,相.

  • mysql timestampdiff datediff_「timestampdiff」datediff()函数 与 timestampdiff()函数的区别 及使用。 – seo实验室…

    mysql timestampdiff datediff_「timestampdiff」datediff()函数 与 timestampdiff()函数的区别 及使用。 – seo实验室…timestampdiff在操作数据库时,经常会使用到“时间范围取值、取时间差”的情况。今天就学习了一个这两个求时间差的函数。1.先从名字上来区分这两个函数的区别。datediff()//看名字“直译”过来的意思是《日期差异》(胡乱翻译的不是很正确哦!)timestampdiff()//这个也“值译”过来《时间戳差异》从名字就能大概区分他们的租作用,一个比较时间戳的,一个是比较日期的。…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号