Golang Go语言中发生死锁的问题

Golang Go语言中发生死锁的问题

package main

import ( “fmt” “math/rand” “sync” “time” )

var wg sync.WaitGroup

//计算一个 64 位随机数的各位的和 func randNumber(x int64) int64 { var sum int64 = 0 for x > 0 { a := x % 10 x = x / 10 sum += a } return sum }

func main() { wg.Add(25) var jobChan = make(chan int64, 10) var resultChan = make(chan int64, 10) go func(jobChan chan<- int64, ) { defer wg.Done() for i:=0;i<1000;i++{ rand.Seed(time.Now().UnixNano()) jobChan <- rand.Int63n(100) } }(jobChan)

for i:=0;i&lt;24;i++{
	go func(jobChan &lt;-chan int64, resultChan chan&lt;- int64, ) {
		defer wg.Done()
		for num:= range jobChan{
			resultChan &lt;- randNumber(num)
		}
	}(jobChan, resultChan)
}

for i:= range resultChan{
	fmt.Println(i)
}
wg.Wait()

}

发生错误:fatal error: all goroutines are asleep - deadlock! 请教一下,为什么会发生死锁的情况?


更多关于Golang Go语言中发生死锁的问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html

8 回复

go<br>package main<br><br>import (<br> "fmt"<br> "math/rand"<br> "sync"<br> "time"<br>)<br><br>var wg sync.WaitGroup<br><br>//计算一个 64 位随机数的各位的和<br>func randNumber(x int64) int64 {<br> var sum int64 = 0<br> for x &gt; 0 {<br> a := x % 10<br> x = x / 10<br> sum += a<br> }<br> return sum<br>}<br><br>func main() {<br> wg.Add(25)<br> var jobChan = make(chan int64, 10)<br> var resultChan = make(chan int64, 10)<br> go func(jobChan chan&lt;- int64, ) {<br> defer wg.Done()<br> for i := 0; i &lt; 1000; i++ {<br> rand.Seed(time.Now().UnixNano())<br> jobChan &lt;- rand.Int63n(100)<br> }<br> close(jobChan) // 此处要关闭 jobChan,否则在 jobChan 的 range 遍历中会一直阻塞<br> }(jobChan)<br><br> for i := 0; i &lt; 24; i++ {<br> go func(jobChan &lt;-chan int64, resultChan chan&lt;- int64, ) {<br> defer wg.Done()<br> for num := range jobChan {<br> resultChan &lt;- randNumber(num)<br> }<br> }(jobChan, resultChan)<br> }<br> // 此处 resultChan 的遍历放到一个 goroutine 中执行,让 wg 的 wait 执行完后主协程直接退出<br> // 如果放在主协程中,也没有关闭 resultChan 的话,也会造成阻塞,就会产生死锁<br> go func() {<br> for i := range resultChan {<br> fmt.Println(i)<br> }<br> }()<br> wg.Wait()<br>}<br>

更多关于Golang Go语言中发生死锁的问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


去看看 waitgroup 实现吧

channel 没有关闭
for num:= range jobChan
永远不会退出

for num:= range jobChan{
resultChan <- randNumber(num)
}
job 1000 个发完之后,这边还一直卡主。
最后的 Wait()也没意义,从 resultChan 读那里也退不出来

原因就是 2l 说的那样,因为 jobChan 和 resultChan 没有 close 阻塞在循环里了,jobChan 就像 2l 那样处理,resultChan 的处理,可以在 wg.Wait()后边 close resultChan,然后再 range resultChan 打印结果

感谢, 刚学习 go,有一些概念改搞不清。但是你这种方法好像会造成接收不完全就会退出。我自己也解决了这个问题了。

<br>package main<br><br>import (<br> "context"<br> "fmt"<br> "math/rand"<br> "sync"<br> "time"<br>)<br><br>var (<br> wg = sync.WaitGroup{} // 用于计数, 让程序正常执行,不会主函数执行完子函数还没执行。计数清 0 则不用等待<br> a int<br> //lock sync.Mutex<br> rwlock sync.RWMutex<br> icons map[string]string<br> loadIconsOnce sync.Once<br> //m sync.Map<br> )<br> <br>func randNumber(x int64) int64 {<br> var sum int64 = 0<br> for x &gt; 0 {<br> a := x % 10<br> x = x / 10<br> sum += a<br> }<br> return sum<br>}<br><br><br>func main() {<br> wg.Add(25)<br> defer wg.Wait()<br> var maxSend = 10<br> var jobChan = make(chan int64, 10)<br> var resultChan = make(chan int64, 10)<br> var lock sync.Mutex<br> ctx, cancel := context.WithCancel(context.Background())<br><br> //var once sync.Once<br> go func(jobChan chan&lt;- int64, ) {<br> for i:=0;i&lt;maxSend;i++{<br> rand.Seed(time.Now().UnixNano())<br> jobChan &lt;- rand.Int63n(100)<br> }<br> close(jobChan)<br> wg.Done()<br> }(jobChan)<br><br> count1 := 1<br> for i:=0;i&lt;24;i++{<br> go func(jobChan &lt;-chan int64, resultChan chan int64, ctx context.Context) {<br> defer wg.Done()<br> for num:= range jobChan{<br> select {<br> case &lt;- ctx.Done():<br> return<br> case resultChan &lt;- randNumber(num):<br> lock.Lock()<br> fmt.Println("count:", count1)<br> count1 += 1<br> lock.Unlock()<br> }<br><br> }<br> }(jobChan, resultChan, ctx)<br> }<br><br> num := maxSend<br> count := 1<br> for value := range resultChan {<br> if num == 1 {<br> fmt.Printf("key:%v, value:%v\n", count, value)<br> cancel()<br> return<br> }else {<br> num -= 1<br> fmt.Printf("key:%v, value:%v\n", count, value)<br> count += 1<br> }<br> }<br>}<br><br>

回复中, 写代码怎么 md 不生效了= =

在Go语言中,死锁是一种常见的并发编程问题,它发生在两个或多个goroutine相互等待对方释放锁,从而导致程序永远阻塞。解决Go语言中的死锁问题,通常需要从以下几个方面入手:

  1. 分析代码逻辑:仔细检查代码中所有锁的获取和释放顺序,确保每个goroutine在持有某个锁的同时,不会尝试去获取其他goroutine已经持有的锁。这可以通过良好的代码设计和清晰的锁管理策略来实现。

  2. 使用sync包中的工具:Go的sync包提供了多种同步机制,如互斥锁(sync.Mutex)、读写锁(sync.RWMutex)和等待组(sync.WaitGroup)等。合理使用这些工具可以有效避免死锁。

  3. 避免嵌套锁:尽量减少嵌套锁的使用,因为嵌套锁很容易引发死锁。如果必须使用嵌套锁,要确保锁的获取顺序一致。

  4. 使用超时机制:在尝试获取锁时,可以设置一个超时时间。如果超时时间到达仍未获取到锁,则放弃获取锁并采取相应的恢复措施。

  5. 调试和检测:使用Go的调试工具(如pprofrace检测器等)来检测和分析死锁问题。这些工具可以帮助你快速定位问题所在。

总之,解决Go语言中的死锁问题需要细致的代码分析和良好的同步机制设计。通过合理使用sync包中的工具、避免嵌套锁、使用超时机制以及借助调试工具,你可以有效地避免和解决死锁问题。

回到顶部