Go 等待并发工作人员完成后再退出
下面的代码有一个明显的问题:程序将在工作人员完成所有工作之前退出 在发送方开始发送数据(必须保留)之前启动工作进程的Goroutines。从发送方函数启动这些goroutine不是一个选项。这样做很容易,但是,需要学习更复杂的同步技术 等待工人完成的正确方法是什么 已尝试关闭Go 等待并发工作人员完成后再退出,go,concurrency,Go,Concurrency,下面的代码有一个明显的问题:程序将在工作人员完成所有工作之前退出 在发送方开始发送数据(必须保留)之前启动工作进程的Goroutines。从发送方函数启动这些goroutine不是一个选项。这样做很容易,但是,需要学习更复杂的同步技术 等待工人完成的正确方法是什么 已尝试关闭worker1CH和worker2CH频道,并向每个工作程序添加专用的sync.WaitGroups package main import ( "log" "math/ran
worker1CH
和worker2CH
频道,并向每个工作程序添加专用的sync.WaitGroups
package main
import (
"log"
"math/rand"
"sync"
)
func main() {
worker1CH := make(chan int, 1)
worker2CH := make(chan int, 1)
// worker for even numbers
go func(in chan int) {
for i := range in {
log.Print(i)
}
}(worker1CH)
// worker for odd numbers
go func(in chan int) {
for i := range in {
log.Print(i)
}
}(worker2CH)
// sender which sends even numbers to worker1CH, and odd numbers to worker2CH
var wg sync.WaitGroup
wg.Add(1)
go func(wg *sync.WaitGroup, evenChan chan int, oddChan chan int) {
defer wg.Done()
data := rand.Perm(10)
for _, i := range data {
switch i%2 {
case 0:
evenChan <- i
default:
oddChan <- i
}
}
}(&wg, worker1CH, worker2CH)
wg.Wait()
}
主程序包
进口(
“日志”
“数学/兰德”
“同步”
)
func main(){
worker1CH:=制造(成交量,1)
worker2CH:=make(chan int,1)
//偶数工人
go func(以成色表示){
对于i:=中的范围{
日志打印(一)
}
}(工人1ch)
//奇数工人
go func(以成色表示){
对于i:=中的范围{
日志打印(一)
}
}(worker2CH)
//向worker1CH发送偶数,向worker2CH发送奇数的发送方
var wg sync.WaitGroup
工作组.添加(1)
go func(wg*sync.WaitGroup,evenChan int,oddChan int){
推迟工作组完成()
数据:=平均兰特(10)
对于u,i:=范围数据{
开关i%2{
案例0:
evenChan使用等待组等待两个接收goroutine完成。使用一个等待组等待两个goroutine
发送所有值后关闭通道,以便退出接收goroutine中的循环
无需等待发送goroutine。灌浆在其他协同工作完成之前完成所有工作
worker1CH := make(chan int, 1)
worker2CH := make(chan int, 1)
var wg sync.WaitGroup
wg.Add(2) // <-- wait for the two receiving goroutines.
// worker for even numbers
go func(wg *sync.WaitGroup, in chan int) {
defer wg.Done() // <--- add this line
for i := range in {
log.Print(i)
}
}(&wg, worker1CH)
// worker for odd numbers
go func(wg *sync.WaitGroup, in chan int) {
defer wg.Done() <-- add this line
for i := range in {
log.Print(i)
}
}(&wg, worker2CH)
// sender which sends even numbers to worker1CH, and odd numbers to worker2CH
go func(evenChan chan int, oddChan chan int) {
defer close(evenChan) // <-- close channel so that receiver exits loop
defer close(oddChan) // <-- ditto
data := rand.Perm(10)
for _, i := range data {
switch i % 2 {
case 0:
evenChan <- i
default:
oddChan <- i
}
}
}(worker1CH, worker2CH)
wg.Wait()
worker1CH:=make(chan int,1)
worker2CH:=make(chan int,1)
var wg sync.WaitGroup
wg.Add(2)//使用等待组等待两个接收goroutine完成。使用一个等待组等待两个goroutine
发送所有值后关闭通道,以便退出接收goroutine中的循环
无需等待发送goroutine。灌浆在其他协同工作完成之前完成所有工作
worker1CH := make(chan int, 1)
worker2CH := make(chan int, 1)
var wg sync.WaitGroup
wg.Add(2) // <-- wait for the two receiving goroutines.
// worker for even numbers
go func(wg *sync.WaitGroup, in chan int) {
defer wg.Done() // <--- add this line
for i := range in {
log.Print(i)
}
}(&wg, worker1CH)
// worker for odd numbers
go func(wg *sync.WaitGroup, in chan int) {
defer wg.Done() <-- add this line
for i := range in {
log.Print(i)
}
}(&wg, worker2CH)
// sender which sends even numbers to worker1CH, and odd numbers to worker2CH
go func(evenChan chan int, oddChan chan int) {
defer close(evenChan) // <-- close channel so that receiver exits loop
defer close(oddChan) // <-- ditto
data := rand.Perm(10)
for _, i := range data {
switch i % 2 {
case 0:
evenChan <- i
default:
oddChan <- i
}
}
}(worker1CH, worker2CH)
wg.Wait()
worker1CH:=make(chan int,1)
worker2CH:=make(chan int,1)
var wg sync.WaitGroup
wg.Add(2)/已经能够创建worker1Done
和worker2Done
频道,然后等待工作完成
还必须将close(evenChan)和close(oddChan)添加到sender函数中,以避免出现致命错误:所有goroutines都处于休眠状态-死锁!
错误
package main
import (
"log"
"math/rand"
"sync"
)
func main() {
worker1CH := make(chan int, 1)
worker2CH := make(chan int, 1)
worker1Done := make(chan bool)
worker2Done := make(chan bool)
// worker for even numbers
go func(in chan int, done chan bool) {
for i := range in {
log.Print(i)
}
done <- true
}(worker1CH, worker1Done)
// worker for odd numbers
go func(in chan int, done chan bool) {
for i := range in {
log.Print(i)
}
done <- true
}(worker2CH, worker2Done)
// sender which sends even numbers to worker1CH, and odd numbers to worker2CH
var wg sync.WaitGroup
wg.Add(1)
go func(wg *sync.WaitGroup, evenChan chan int, oddChan chan int) {
defer wg.Done()
data := rand.Perm(10)
for _, i := range data {
switch i%2 {
case 0:
evenChan <- i
default:
oddChan <- i
}
}
close(evenChan)
close(oddChan)
}(&wg, worker1CH, worker2CH)
wg.Wait()
<- worker1Done
<- worker2Done
}
主程序包
进口(
“日志”
“数学/兰德”
“同步”
)
func main(){
worker1CH:=制造(成交量,1)
worker2CH:=make(chan int,1)
worker1Done:=make(chan bool)
worker2Done:=make(chan bool)
//偶数工人
go func(在成交量中,完成成交量){
对于i:=中的范围{
日志打印(一)
}
完成已经能够创建worker1Done
和worker2Done
频道,然后等待工作完成
还必须将close(evenChan)和close(oddChan)添加到sender函数中,以避免出现致命错误:所有goroutines都处于休眠状态-死锁!
错误
package main
import (
"log"
"math/rand"
"sync"
)
func main() {
worker1CH := make(chan int, 1)
worker2CH := make(chan int, 1)
worker1Done := make(chan bool)
worker2Done := make(chan bool)
// worker for even numbers
go func(in chan int, done chan bool) {
for i := range in {
log.Print(i)
}
done <- true
}(worker1CH, worker1Done)
// worker for odd numbers
go func(in chan int, done chan bool) {
for i := range in {
log.Print(i)
}
done <- true
}(worker2CH, worker2Done)
// sender which sends even numbers to worker1CH, and odd numbers to worker2CH
var wg sync.WaitGroup
wg.Add(1)
go func(wg *sync.WaitGroup, evenChan chan int, oddChan chan int) {
defer wg.Done()
data := rand.Perm(10)
for _, i := range data {
switch i%2 {
case 0:
evenChan <- i
default:
oddChan <- i
}
}
close(evenChan)
close(oddChan)
}(&wg, worker1CH, worker2CH)
wg.Wait()
<- worker1Done
<- worker2Done
}
主程序包
进口(
“日志”
“数学/兰德”
“同步”
)
func main(){
worker1CH:=制造(成交量,1)
worker2CH:=make(chan int,1)
worker1Done:=make(chan bool)
worker2Done:=make(chan bool)
//偶数工人
go func(在成交量中,完成成交量){
对于i:=中的范围{
日志打印(一)
}
完成因为您的发送者有固定的大小,所以它将自己退出,您只需关闭读卡器通道并等待
package main
import (
"log"
"math/rand"
"sync"
)
func reader(in chan int, wg *sync.WaitGroup) {
defer wg.Done()
for i := range in {
log.Print(i)
}
}
func main() {
var wg sync.WaitGroup
worker1CH := make(chan int, 1)
worker2CH := make(chan int, 1)
wg.Add(1)
// worker for even numbers
go reader(worker1CH, &wg)
wg.Add(1)
// worker for odd numbers
go reader(worker2CH, &wg)
// sender which sends even numbers to worker1CH, and odd numbers to worker2CH
sender(worker1CH, worker2CH)
close(worker2CH)
close(worker1CH)
wg.Wait()
}
func sender(evenChan chan int, oddChan chan int) {
data := rand.Perm(10)
for _, i := range data {
switch i % 2 {
case 0:
evenChan <- i
default:
oddChan <- i
}
}
}
主程序包
进口(
“日志”
“数学/兰德”
“同步”
)
func读取器(在chan int中,wg*sync.WaitGroup){
推迟工作组完成()
对于i:=中的范围{
日志打印(一)
}
}
func main(){
var wg sync.WaitGroup
worker1CH:=制造(成交量,1)
worker2CH:=make(chan int,1)
工作组.添加(1)
//偶数工人
go阅读器(worker1CH和wg)
工作组.添加(1)
//奇数工人
go阅读器(worker2CH和wg)
//向worker1CH发送偶数,向worker2CH发送奇数的发送方
发送方(worker1CH、worker2CH)
关闭(worker2CH)
关闭(worker1CH)
wg.Wait()
}
func发送方(evenChan int、oddChan int){
数据:=平均兰特(10)
对于u,i:=范围数据{
开关i%2{
案例0:
evenChan因为您的发件人有固定的大小,所以它将自己退出,您可以关闭频道等待读者
package main
import (
"log"
"math/rand"
"sync"
)
func reader(in chan int, wg *sync.WaitGroup) {
defer wg.Done()
for i := range in {
log.Print(i)
}
}
func main() {
var wg sync.WaitGroup
worker1CH := make(chan int, 1)
worker2CH := make(chan int, 1)
wg.Add(1)
// worker for even numbers
go reader(worker1CH, &wg)
wg.Add(1)
// worker for odd numbers
go reader(worker2CH, &wg)
// sender which sends even numbers to worker1CH, and odd numbers to worker2CH
sender(worker1CH, worker2CH)
close(worker2CH)
close(worker1CH)
wg.Wait()
}
func sender(evenChan chan int, oddChan chan int) {
data := rand.Perm(10)
for _, i := range data {
switch i % 2 {
case 0:
evenChan <- i
default:
oddChan <- i
}
}
}
主程序包
进口(
“日志”
“数学/兰德”
“同步”
)
func读取器(在chan int中,wg*sync.WaitGroup){
推迟工作组完成()
对于i:=中的范围{
日志打印(一)
}
}
func main(){
var wg sync.WaitGroup
worker1CH:=制造(成交量,1)
worker2CH:=make(chan int,1)
工作组.添加(1)
//偶数工人
go阅读器(worker1CH和wg)
工作组.添加(1)
//奇数工人
go阅读器(worker2CH和wg)
//向worker1CH发送偶数,向worker2CH发送奇数的发送方
发送方(worker1CH、worker2CH)
关闭(worker2CH)
关闭(worker1CH)
wg.Wait()
}
func发送方(evenChan int、oddChan int){
数据:=平均兰特(10)
对于u,i:=范围数据{
开关i%2{
案例0:
evenChan perfect还添加了一种使用通道进行同步以备将来参考的方法。谢谢!我想知道什么更有效…完成通道或等待组…在更复杂的场景中,使用等待组更容易获得正确的代码。perfect还添加了一种使用通道进行同步以备将来参考的方法。谢谢你!我想知道什么更有效…一个完成频道,还是一个等待组…在更复杂的场景中,更容易获得正确的代码