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

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

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

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • android json解析及简单例子

    android json解析及简单例子android2.3提供的json解析类android的json解析部分都在包org.json下,主要有以下几个类:JSONObject:可以看作是一个json对象,这是系统中有关JSON定义的基本

    2022年7月2日
    22
  • linux系统添加静态路由命令_静态路由和默认路由小结

    linux系统添加静态路由命令_静态路由和默认路由小结linux下静态路由修改命令方法一:添加路由routeadd-net192.168.0.0/24gw192.168.0.1routeadd-host192.168.1.1dev192.168.0.1删除路由routedel-net192.168.0.0/24gw192.168.0.1add增加路由del删除路由-net设置到某个网段的路由-host设置到某台主…

    2022年10月4日
    2
  • curl_init php_宝塔php开启curl扩展

    curl_init php_宝塔php开启curl扩展安装某些PHP源码如CMSTOP时需求系统开启curl扩展,这需要修改PHP的配置,在Windows中只需简单三步。一、window下安装php_curl支持1.将PHP安装文件夹下的三个文件php_curl.dll(可能在ext文件夹中),libeay32.dll,ssleay32.dll复制到%windir%/system32下;2.打开php.ini(可能在PHP环境的安装目录下,默认…

    2022年10月9日
    3
  • 如何以貌取人【蔡澜】

    如何以貌取人【蔡澜】

    2021年9月2日
    64
  • 晶晶图js小女孩行走动画

    晶晶图js小女孩行走动画1<!DOCTYPEhtml>2<htmllang=”en”>3<head>4<metacharset=”UTF-8″>5<title>Document</title>6<styletype=”text/css”>7…

    2022年7月17日
    24
  • 【参赛作品29】基于openGauss数据库设计人力资源管理系统实验「建议收藏」

    【参赛作品29】基于openGauss数据库设计人力资源管理系统实验「建议收藏」本文作者:瓜西西本文主要面向openGauss数据库初学者,帮助初学者完成一些简单的数据库管理以及GUI,设计一个简单的人力资源管理系统。本文只包含部分代码,读者需要结合自己的数据库弹性公网、数据库用户及其密码等自身信息做出相应的修改。一、实验环境使用程序:putty.exe;IntelliJIDEA2021.1.1;apache-tomcat-9.0.46服务器名称:ecs-d8b3弹性公网:121.36.79.196端口号:26000表空间名:human_resource_

    2022年5月24日
    36

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

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