Golang goroutine不';不要在通道内运行
我正试图实现一个字数计算程序,但第一步我遇到了一些问题 这是我的密码:Golang goroutine不';不要在通道内运行,go,Go,我正试图实现一个字数计算程序,但第一步我遇到了一些问题 这是我的密码: package main import ( "fmt" "os" "bufio" "sync" ) // Load data into channel func laodData(arr []string,channel chan string,wg sync.WaitGroup) { for _,path := range arr { file,err := os
package main
import (
"fmt"
"os"
"bufio"
"sync"
)
// Load data into channel
func laodData(arr []string,channel chan string,wg sync.WaitGroup) {
for _,path := range arr {
file,err := os.Open(path)
fmt.Println("begin to laodData ", path)
if err != nil {
fmt.Println(err)
os.Exit(-1)
}
defer file.Close()
reader := bufio.NewReaderSize(file, 32*10*1024)
i := 0
for {
line,err := reader.ReadString('\n')
channel <- line
if err != nil {
break
}
i++
if i%200 == 0 {
fmt.Println(i," lines parsed")
}
}
fmt.Println("finish laodData ", path)
}
wg.Done()
}
// dispatch data lines into different mappers
func dispatcher(channel chan string,wg sync.WaitGroup){
fmt.Println("pull data 11")
line,ok := <- channel
fmt.Println(ok)
for ok {
fmt.Println(line)
line,ok = <- channel
}
fmt.Println("pull data 22")
wg.Done()
}
func main() {
path := os.Args
if len(path) < 2 {
fmt.Println("Need Input Files")
os.Exit(0)
}
var wg sync.WaitGroup
wg.Add(2)
channel := make(chan string)
defer close(channel)
fmt.Println("before dispatcher")
go laodData(path[1:],channel,wg)
go dispatcher(channel,wg)
wg.Wait()
fmt.Println("after dispatcher")
}
谢谢 程序在主goroutine退出时终止,因此
dispatcher()
没有时间做任何事情。您需要在main()
中阻塞,直到dispatcher()
完成。通道可用于以下用途:
package main
import (
"fmt"
"os"
"bufio"
)
var done = make(chan bool) // create channel
// Load files and send them into a channel for mappers reading.
func dispatcher(arr []string,channel chan string) {
for _,path := range arr {
file,err := os.Open(path)
fmt.Println("begin to dispatch ", path)
if err != nil {
fmt.Println(err)
os.Exit(-1)
}
defer file.Close()
reader := bufio.NewReaderSize(file, 32*10*1024)
i := 0
for {
line,_ := reader.ReadString('\n')
channel <- line
i++
if i%200 == 0 {
fmt.Println(i," lines parsed")
}
}
fmt.Println("finish dispatch ", path)
}
done <- true // notify main() of completion
}
func main() {
path := os.Args
if len(path) < 2 {
fmt.Println("Need Input Files")
os.Exit(0)
}
channel := make(chan string)
fmt.Println("before dispatcher")
go dispatcher(path[1:],channel)
<-done // wait for dispatcher()
fmt.Println("after dispatcher")
}
主程序包
进口(
“fmt”
“操作系统”
“布菲奥”
)
var done=make(chan bool)//创建通道
//加载文件并将其发送到通道中,以便映射程序读取。
func调度程序(arr[]字符串,通道chan字符串){
对于u,路径:=范围arr{
文件,错误:=os.Open(路径)
fmt.Println(“开始调度”,路径)
如果错误!=零{
fmt.Println(错误)
操作系统退出(-1)
}
延迟文件。关闭()
reader:=bufio.NewReaderSize(文件,32*10*1024)
i:=0
为了{
第行,u:=reader.ReadString('\n')
通道I在没有文件I/O的Go操场上运行;它在通道上发送随机数
@Victor Deryagin的解释和他使用“完成”通道的建议是正确的。出现死锁的原因是您的goroutine在通道上发送,但没有人从中读取,因此程序在这一点上被卡住。在上面的链接中,我添加了一个consumer goroutine。然后程序按预期并发运行
请注意,要等待几个goroutine,它更清晰、更易于使用。原始问题中需要解决两个问题
发送完所有数据后,必须关闭频道。在funclaodData
中,请使用close(channel)post发送所有数据
将sync.Waitgroup
作为引用传递。您正在将wg作为参数中的值发送给以下函数…laodData
和dispatcher函数
解决这两个问题将解决死锁问题。代码中出现死锁的原因如下:
- 不关闭发送通道将导致下游通道等待较长时间
- 将
sync.Waitgroup
的参数作为值发送。应将其作为引用发送,否则将创建所发送对象的新副本
在这种情况下,在go dispatcher(路径[1:],通道)
中删除go
会更简单。谢谢@dystory,我需要在主线程中的dispatcher之外做些其他事情。嗨,维克托,我听从了你的建议,但我遇到了死锁!问题。**抛出:所有Goroutine都处于休眠状态-死锁!通道@MrROYdispatcher()
将内容发送到一个频道
,作为参数传递,另一端没有人接受它,因此它的goroutine被阻止。main()
也被阻止,因为它正在等待dispatcher()
完成。嗨,@VictorYagin感谢你的伟大的anwser,但我给频道添加了一个接收器,它仍然死锁。
package main
import (
"fmt"
"os"
"bufio"
)
var done = make(chan bool) // create channel
// Load files and send them into a channel for mappers reading.
func dispatcher(arr []string,channel chan string) {
for _,path := range arr {
file,err := os.Open(path)
fmt.Println("begin to dispatch ", path)
if err != nil {
fmt.Println(err)
os.Exit(-1)
}
defer file.Close()
reader := bufio.NewReaderSize(file, 32*10*1024)
i := 0
for {
line,_ := reader.ReadString('\n')
channel <- line
i++
if i%200 == 0 {
fmt.Println(i," lines parsed")
}
}
fmt.Println("finish dispatch ", path)
}
done <- true // notify main() of completion
}
func main() {
path := os.Args
if len(path) < 2 {
fmt.Println("Need Input Files")
os.Exit(0)
}
channel := make(chan string)
fmt.Println("before dispatcher")
go dispatcher(path[1:],channel)
<-done // wait for dispatcher()
fmt.Println("after dispatcher")
}