go - 所有的 goroutine 都是休眠死锁
问题描述
模拟我的真正问题我有这个代码。
基本上,数组“字母”的每个元素及其索引都被发送到一个 goroutine 以将其与“x”进行比较,然后它通过通道发送响应。我的想法是它在“x”线程上运行,在实际情况下我使用 8 个线程。
package main
import (
"strconv"
"sync"
)
var wg sync.WaitGroup
const sizeLetters = 12
func detectX(ch2 chan int, j int, letters [sizeLetters]string) {
if letters[j] == "x" {
ch2 <- j
}else{
ch2 <- -1
}
}
func main() {
ch1 := make(chan int)
ch2 := make(chan int)
letters := [sizeLetters]string{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l"}
threads:= 4
wg.Add(threads)
for i := 0; i < threads; i++ {
go func() {
for {
j, ok := <-ch1
if !ok {
wg.Done()
}
detectX(ch2, j, letters)
}
}()
}
for i := 0; i < sizeLetters; i++ {
ch1<-i // add i to the queue
}
k, ok := <-ch2 //k contains the position of X, if exist
if !ok {
wg.Done()
}
if k != -1 { //when exist
println("X exist in position: " + strconv.Itoa(k))
}
println("X doesn´t exist")
close(ch2)
close(ch1)
wg.Wait()
}
解决方案
声誉不足,无法发表评论。因此,代替注释,这里是代码的替代版本:
package main
import (
"fmt"
"sync"
)
var wg sync.WaitGroup
const sizeLetters = 12
func detectX(ch2 chan int, j int, letters [sizeLetters]string) {
if letters[j] == "x" {
ch2 <- j
}
}
func main() {
ch1 := make(chan int)
ch2 := make(chan int)
letters := [sizeLetters]string{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l"}
threads := 4
wg.Add(threads)
for i := 0; i < threads; i++ {
go func() {
for {
j, ok := <-ch1
if !ok {
wg.Done()
return
}
detectX(ch2, j, letters)
}
}()
}
// Use a goroutine to close ch2. It is only safe to do this
// after all the other goroutines have exited.
go func() {
wg.Wait()
close(ch2)
}()
for i := 0; i < sizeLetters; i++ {
ch1 <- i // add i to the queue
}
close(ch1)
if k, ok := <-ch2; ok && k != -1 { //when exist
fmt.Println("X exist in position:", k)
} else {
fmt.Println("X doesn´t exist")
}
}
它仍然存在一些与数据相关的问题(除非letters
保证数组不包含重复项):
- 也就是说,如果数组中有多个
"x"
,goroutines 不会全部退出。也就是说,main()
不流失ch2
。 - 如果有多个
threads
"x"
值,那么代码将在顶层for
循环中死锁,main()
因为写入ch1
将用完未阻塞的 goroutine 来消耗它们。- 如果您知道数组中可能有多少
"x"
个值,则letters
可以使ch2
通道变深:ch2 := make(chan int, depth)
。这将允许所有 goroutines 退出,但ch2
可能仍包含未排水的数据。
- 如果您知道数组中可能有多少
推荐阅读
- javascript - 先前元素列表的 CSS 应用于 javascript 中的新元素列表
- apache-spark - 结构化流写入不同的镶木地板文件夹
- python - 我需要在 Python 中制作一个较小版本的 128A 条形码,但没有成功
- c# - Json.net 将平面对象序列化为键值对数组
- python - TypeError:__str__ 返回非字符串(类型错误)
- php - SQLSTATE [23000]:违反完整性约束:1048 列“profile_percentage”在原则上不能为空
- php - move_uploaded_file 给出“无法打开流:权限被拒绝”
- r - 如何从 MVC 控制器操作方法触发 R 脚本并将结果接收到数据表中?
- c - 字数统计程序打印不同的字数
- r - downloadHandler (Shiny) 误解用户路径名中的斜杠