英文:
Do sending more than 8 element to a channel can result in deadlock?
问题
package main
import (
"fmt"
"time"
)
func printCount(c chan int) {
num := 0
for num >= 0 {
num = <-c
fmt.Print(num, " ")
}
}
func main() {
a := []int{8, 6, 7, 5, 3, 0, 9, -1, 3, 4}
// 如果我使用 a := []int{8, 6, 7, 5, 3, 0, 9, -1},那么程序就能正常工作
c := make(chan int)
go printCount(c)
for _, v := range a {
c <- v
}
time.Sleep(time.Second * 1)
fmt.Println("主函数结束")
}
我尝试使用Go语言将切片的元素发送到通道,并打印出来。现在,当切片的元素数量达到8个时,程序能正常工作。但是,当我添加第9个元素时,会出现死锁的情况,我不知道为什么。我尝试使用waitgroup
来解决这个问题,但仍然无法正常工作。
英文:
package main
import (
"fmt"
"time"
)
func printCount(c chan int) {
num := 0
for num >= 0 {
num = <-c
fmt.Print(num, " ")
}
}
func main() {
a := []int{8, 6, 7, 5, 3, 0, 9, -1, 3, 4}
// If i use a := []int{8, 6, 7, 5, 3, 0, 9, -1} then it works fine
c := make(chan int)
go printCount(c)
for _, v := range a {
c <- v
}
time.Sleep(time.Second * 1)
fmt.Println("End of main")
}
I try to send element of the slice to the channel and print it using golang.
Now upto 8 element the program works fine.
As i am adding 9th element in slice then deadlock conditions occures dont know why. I used to solve that by using the waitgroup but still not working.
答案1
得分: 1
通过(无缓冲的)通道发送一个值总是阻塞的,直到它在其他地方被接收。
我认为你在这里的意图是发送所有的值,然后只在它们大于或等于0时打印它们?你可以像这样修改你的printCount
函数:
func printCount(c chan int) {
for num := range c {
if num >= 0 {
fmt.Print(num, " ")
}
}
}
https://goplay.space/#m5eT9AYDH-Q
英文:
Sending a value through an (unbuffered) channel is always blocking, until it is received somewhere else.
I think your intention here is to send all values and then only print them if they are 0 or greater? You could alter your printCount
like this:
func printCount(c chan int) {
for num := range c {
if num >= 0 {
fmt.Print(num, " ")
}
}
}
答案2
得分: 0
你好,只需将c := make(chan int)更改为c := make(chan int, 100),其中100是通道的最大容量:
package main
import (
"fmt"
"time"
)
func printCount(c chan int) {
num := 0
for num >= 0 {
num = <-c
fmt.Print(num, " ")
}
}
func main() {
a := []int{8, 6, 7, 5, 3, 0, 9, -1, 3, 4}
// 如果我使用 a := []int{8, 6, 7, 5, 3, 0, 9, -1},那么它可以正常工作
c := make(chan int, 40)
go printCount(c)
for _, v := range a {
c <- v
}
time.Sleep(time.Second * 1)
fmt.Println("End of main")
}
结果:
8 6 7 5 3 0 9 -1 End of main
英文:
Hi just change c := make(chan int) to c := make(chan int, 100)
where 100 is highest capacity of your channel:
package main
import (
"fmt"
"time"
)
func printCount(c chan int) {
num := 0
for num >= 0 {
num = <-c
fmt.Print(num, " ")
}
}
func main() {
a := []int{8, 6, 7, 5, 3, 0, 9, -1, 3, 4}
// If i use a := []int{8, 6, 7, 5, 3, 0, 9, -1} then it works fine
c := make(chan int, 40)
go printCount(c)
for _, v := range a {
c <- v
}
time.Sleep(time.Second * 1)
fmt.Println("End of main")
}
result:
8 6 7 5 3 0 9 -1 End of main
答案3
得分: 0
printCount
goroutine在处理负值时会退出。更准确地说,值-1
会停止它。
在这里,printCount
goroutine是唯一可以读取通道值的goroutine。当这个goroutine退出时,通道中就无法再写入值,因为该通道是无缓冲的。
注意:该通道是无缓冲的,因此不能包含任何值。无缓冲通道是Go语言中一种将值从一个goroutine安全地传递给另一个goroutine的同步方式。
解决方案
你应该读取通道,直到不再需要处理更多元素。
不再需要使用time.Sleep(time.Second * 1)
,printCount
现在会阻塞主goroutine直到完成!
package main
import (
"fmt"
"time"
)
func printCount(c chan int) {
// 如果通道为空(或无缓冲)且已关闭,则退出。
for num := range c {
if num >= 0 {
fmt.Print(num, " ")
}
}
}
func main() {
a := []int{8, 6, 7, 5, 3, 0, 9, -1, 3, 4}
c := make(chan int)
go func(){
// 在发送最后一个值后关闭通道
defer close(c)
for _, v := range a {
c <- v
}
}()
printCount(c)
fmt.Println("主函数结束")
}
英文:
The printCount
goroutine exits if a negative value is processed.
More precisely, the value -1
is stopping it.
Here the printCount
goroutine is the only goroutine that can read the channel values. When this goroutine exits no more writing are possible in the channel because the channel is unbuffered.
NB: The channel is unbuffered and thus cannot contains any value. A unbuffered channel is a golang idiom to concurrently safe pass values from a goroutine to another synchronously.
Solution
You should read the channel until no more element need to be processed.
No more need to use time.Sleep(time.Second * 1)
, the printCount
is now blocking the main goroutine until finished !
package main
import (
"fmt"
"time"
)
func printCount(c chan int) {
// exits if the channel is empty (or unbuffered) and closed.
for num := range c {
if num >= 0 {
fmt.Print(num, " ")
}
}
}
func main() {
a := []int{8, 6, 7, 5, 3, 0, 9, -1, 3, 4}
c := make(chan int)
go func(){
// close the channel after sending the last value
defer close(c)
for _, v := range a {
c <- v
}
}()
printCount(c)
fmt.Println("End of main")
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论