Go 等待所有围棋程序完成
第一次使用围棋,尝试让围棋例程和Go 等待所有围棋程序完成,go,concurrency,goroutine,Go,Concurrency,Goroutine,第一次使用围棋,尝试让围棋例程和WaitGroups工作 我有一个包含100行数据的CSV文件。(101包括收割台) 我有以下简单的代码: package main import ( "bufio" "fmt" "io" "os" "sync" "time" ) func main() { start := time.Now() numRows := 0 waitGroup := sync.WaitGroup{}
WaitGroups
工作
我有一个包含100行数据的CSV文件。(101包括收割台)
我有以下简单的代码:
package main
import (
"bufio"
"fmt"
"io"
"os"
"sync"
"time"
)
func main() {
start := time.Now()
numRows := 0
waitGroup := sync.WaitGroup{}
file, _ := os.Open("./data.csv")
scanner := bufio.NewScanner(file)
scanner.Scan() // to read the header
for scanner.Scan() {
err := scanner.Err()
if err != nil && err != io.EOF {
panic(err)
}
waitGroup.Add(1)
go (func() {
numRows++
waitGroup.Done()
})()
}
waitGroup.Wait()
file.Close()
fmt.Println("Finished parsing ", numRows)
fmt.Println("Elapsed time in seconds: ", time.Now().Sub(start))
}
当我运行它时,numRows
输出每次在94到100之间波动。我希望每次都是100。如果我在包含10行数据的CSV上运行相同的代码,它每次都会输出10
在我看来,最后几次围棋没有及时结束
我尝试了以下失败的方法:
- 使用
代替CsvReader
扫描仪
- 移动
添加到匿名函数下面waitGroup。将(1)
- 将匿名func移出到包级别的作用域func中(并使用ptr传递内容)
我遗漏了什么?在不同的goroutine中同时修改单个变量是不安全的。您对
numRows
的一些更新将丢失,有时您的程序可能会崩溃
使用互斥锁保护numRows
变量,或使用其中一个函数以原子方式进行添加:
var numRows int32
// ...
go (func() {
atomic.AddInt32(&numRows, 1)
waitGroup.Done()
})()
您如何处理此代码:
for scanner.Scan() {
err := scanner.Err()
if err != nil && err != io.EOF {
panic(err)
}
waitGroup.Add(1)
go (func() {
numRows++
waitGroup.Done()
})()
}
实际上,所有的工作都在一个主goroutine中完成,只有numRows
increment使用单独的goroutine。我认为这可以简化为简单的增量:
for scanner.Scan() {
err := scanner.Err()
if err != nil && err != io.EOF {
panic(err)
}
numRows++
}
如果您想模拟并行解析和管道,可以使用通道。只让一个goroutine负责计数器增量。每当另一个goroutine想要递增计数器时,它就会向该通道发送一条消息
在种族检测器下运行:-)毫无疑问,它可以简化,但我不认为这是问题的关键。是的,我只是分享了一些如何与ChannelsAh序列化访问的想法。这很有意义。我的代码非常脆弱,但关键是我在go中掌握了并发性,所以这将我推向了正确的方向。谢谢你已经说过了,这是有道理的。我想我现在开始更了解goroutines了。谢谢你对原子函数的了解。