所有的 goroutines 都是 sleep deadlock
All goroutines are sleep deadlock
模拟我的真实问题我有这段代码。
基本上,数组“letters”的每个元素及其索引被发送到 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"
个值,那么代码将死锁在 main()
的顶层 for
循环中,因为写入 ch1
将从未阻塞的 goroutines 中 运行 消耗它们。
- 如果您知道
letters
数组中可能有多少 "x"
个值,您可以使 ch2
通道那么深:ch2 := make(chan int, depth)
。这将允许所有 goroutines 退出,但 ch2
可能仍包含未耗尽的数据。
模拟我的真实问题我有这段代码。
基本上,数组“letters”的每个元素及其索引被发送到 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"
个值,那么代码将死锁在main()
的顶层for
循环中,因为写入ch1
将从未阻塞的 goroutines 中 运行 消耗它们。- 如果您知道
letters
数组中可能有多少"x"
个值,您可以使ch2
通道那么深:ch2 := make(chan int, depth)
。这将允许所有 goroutines 退出,但ch2
可能仍包含未耗尽的数据。
- 如果您知道