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<24;i++{
go func(jobChan <-chan int64, resultChan chan<- int64, ) {
defer wg.Done()
for num:= range jobChan{
resultChan <- 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
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 > 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<- int64, ) {<br> defer wg.Done()<br> for i := 0; i < 1000; i++ {<br> rand.Seed(time.Now().UnixNano())<br> jobChan <- rand.Int63n(100)<br> }<br> close(jobChan) // 此处要关闭 jobChan,否则在 jobChan 的 range 遍历中会一直阻塞<br> }(jobChan)<br><br> for i := 0; i < 24; i++ {<br> go func(jobChan <-chan int64, resultChan chan<- int64, ) {<br> defer wg.Done()<br> for num := range jobChan {<br> resultChan <- 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 > 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<- int64, ) {<br> for i:=0;i<maxSend;i++{<br> rand.Seed(time.Now().UnixNano())<br> jobChan <- rand.Int63n(100)<br> }<br> close(jobChan)<br> wg.Done()<br> }(jobChan)<br><br> count1 := 1<br> for i:=0;i<24;i++{<br> go func(jobChan <-chan int64, resultChan chan int64, ctx context.Context) {<br> defer wg.Done()<br> for num:= range jobChan{<br> select {<br> case <- ctx.Done():<br> return<br> case resultChan <- 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语言中的死锁问题,通常需要从以下几个方面入手:
-
分析代码逻辑:仔细检查代码中所有锁的获取和释放顺序,确保每个goroutine在持有某个锁的同时,不会尝试去获取其他goroutine已经持有的锁。这可以通过良好的代码设计和清晰的锁管理策略来实现。
-
使用
sync
包中的工具:Go的sync
包提供了多种同步机制,如互斥锁(sync.Mutex
)、读写锁(sync.RWMutex
)和等待组(sync.WaitGroup
)等。合理使用这些工具可以有效避免死锁。 -
避免嵌套锁:尽量减少嵌套锁的使用,因为嵌套锁很容易引发死锁。如果必须使用嵌套锁,要确保锁的获取顺序一致。
-
使用超时机制:在尝试获取锁时,可以设置一个超时时间。如果超时时间到达仍未获取到锁,则放弃获取锁并采取相应的恢复措施。
-
调试和检测:使用Go的调试工具(如
pprof
、race
检测器等)来检测和分析死锁问题。这些工具可以帮助你快速定位问题所在。
总之,解决Go语言中的死锁问题需要细致的代码分析和良好的同步机制设计。通过合理使用sync
包中的工具、避免嵌套锁、使用超时机制以及借助调试工具,你可以有效地避免和解决死锁问题。