文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

golang中死锁的触发事件是什么

2023-07-05 13:53

关注

这篇文章主要介绍了golang中死锁的触发事件是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇golang中死锁的触发事件是什么文章都会有所收获,下面我们一起来看看吧。

1、Golang中死锁的触发条件

1.1 书上关于死锁的四个必要条件的讲解

发生死锁时,线程永远不能完成,系统资源被阻碍使用,以致于阻止了其他作业开始执行。在讨论处理死锁问题的各种方法之前,我们首先深入讨论一下死锁特点。

必要条件:

如果在一个系统中以下四个条件同时成立,那么就能引起死锁:

我们强调所有四个条件必须同时成立才会出现死锁。循环等待条件意味着占有并等待条件,这样四个条件并不完全独立。

图示例:

golang中死锁的触发事件是什么

线程1、线程2都尝试获取对方未释放的资源,从而会一直阻塞,导致死锁发生。

1.2 Golang 死锁的触发条件

看完了书上关于死锁的介绍,感觉挺清晰的,但是实际上到了使用或者看代码时,自己去判断是否会发生死锁却是模模糊糊的,难以准确判断出来。所以特意去网上找了些资料学习,特此记录。

golang中死锁的触发条件:

死锁是当 Goroutine 被阻塞而无法解除阻塞时产生的一种状态。注意:for 死循环不能算在这里,虽然空for循环是实现了阻塞的效果,但是实际上goroutine是处于运行状态的。

1.3 golang 中阻塞的场景

1 sync.Mutex、sync.RWMutex

golang中的锁是不可重入锁,对已经上了锁的写锁,再次申请锁是会报死锁。上了读锁的锁,再次申请写锁会报死锁,而申请读锁不会报错。

写写冲突,读写冲突,读读不冲突。

func main() {var lock sync.Mutexlock.Lock()lock.Lock()}   //报死锁错误
func main() {var lock sync.RWMutexlock.RLock()lock.Lock()}//报死锁错误
func main() {var lock sync.RWMutexlock.RLock()lock.RLock()}//正常执行

2 sync.WaitGroup

一个不会减少的 WaitGroup 会永久阻塞。

func main() {var wg sync.WaitGroupwg.Add(1)wg.Wait()  //报死锁错误}

3 空 select

空 select 会一直阻塞。

package mainfunc main() {select {}}//报死锁错误

4 channel

为 nil 的channel 发送、接受数据都会阻塞。

func main() {var ch chan struct{}ch <- struct{}{}}//报死锁错误

无缓冲的channel 发送、接受数据都会阻塞。

func main() {ch := make(chan struct{})<- ch}//报死锁错误

channel 缓冲区满了的,继续发送数据会阻塞。

2、死锁案例讲解

2.1 案例一:空 select{}

package mainfunc main() {select {}}

以上面为例子,select 语句会 造成 当前 goroutine 阻塞,但是却无法解除阻塞,所以会导致死锁。

2.2 案例二:从无缓冲的channel接受、发送数据

func main() {ch := make(chan struct{})//ch <- struct{}{} //发送<- ch //接受fmt.Println("main over!")}

发生原因:

上面创建了一个 名为:ch 的channel,没有缓冲空间。当向无缓存空间的channel 发送或者接受数据时,都会阻塞,但是却无法解除阻塞,所以会导致死锁。

解决方案:边接受边读取

package main // 方式1func recv(c chan int) {ret := <-cfmt.Println("接收成功", ret)}func main() {ch := make(chan int)go recv(ch) // 启用goroutine从通道接收值ch <- 10fmt.Println("发送成功")} // 方式2func main() {   ch := make(chan int,1)   ch<-1   println(<-ch)}

2.3 案例三:从空的channel中读取数据

package mainimport ("fmt""time")func request(index int,ch chan<- string)  {time.Sleep(time.Duration(index)*time.Second)s := fmt.Sprintf("编号%d完成",index)ch <- s}func main() {ch := make(chan string, 10)fmt.Println(ch,len(ch))for i := 0; i < 4; i++ {go request(i, ch)}for ret := range ch{ //当 ch 中没有数据的时候,for range ch 会发生阻塞,但是无法解除阻塞,发生死锁fmt.Println(len(ch))fmt.Println(ret)}}

发生原因:

当 ch 中没有数据的时候,就是从空的channel中接受数据,for range ch 会发生阻塞,但是无法解除阻塞,发生死锁。

解决办法:当数据发送完了过后,close channel

package mainimport ("fmt""sync""time")var wg sync.WaitGroupfunc request(index int,ch chan<- string)  {time.Sleep(time.Duration(index)*time.Second)s := fmt.Sprintf("编号%d完成",index)ch <- swg.Done()}func main() {ch := make(chan string, 10)for i := 0; i < 4; i++ {wg.Add(1)go request(i, ch)}go func() {wg.Wait()close(ch)}()LOOP:for {select {case i,ok := <-ch: // select会一直等待,直到某个case的通信操作完成时,就会执行case分支对应的语句        if !ok {          break LOOP        }println(i)default:time.Sleep(time.Second)fmt.Println("无数据")}}}

2.4 案例四:给满了的channel发送数据

func main() {ch := make(chan struct{}, 3)for i := 0; i < 4; i++ {ch <- struct{}{}}}

发生原因:

ch 是一个带缓冲的channel,但是只能缓冲三个struct,当channel满了过后,继续往channel发送数据会阻塞,但是无法解除阻塞,发生死锁。

解决办法:读取channel中的数据

package mainimport ("fmt""sync""time")var wg sync.WaitGroupfunc main() {ch := make(chan struct{}, 3)go func() {for {select {case i, ok := <- ch:wg.Done()fmt.Println(i)if !ok {return}}}}()for i := 0; i < 4; i++ {wg.Add(1)ch <- struct{}{}}wg.Wait()}

关于“golang中死锁的触发事件是什么”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“golang中死锁的触发事件是什么”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注编程网行业资讯频道。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯