Go 等待并发工作人员完成后再退出

Go 等待并发工作人员完成后再退出,go,concurrency,Go,Concurrency,下面的代码有一个明显的问题:程序将在工作人员完成所有工作之前退出 在发送方开始发送数据(必须保留)之前启动工作进程的Goroutines。从发送方函数启动这些goroutine不是一个选项。这样做很容易,但是,需要学习更复杂的同步技术 等待工人完成的正确方法是什么 已尝试关闭worker1CH和worker2CH频道,并向每个工作程序添加专用的sync.WaitGroups package main import ( "log" "math/ran

下面的代码有一个明显的问题:程序将在工作人员完成所有工作之前退出

在发送方开始发送数据(必须保留)之前启动工作进程的Goroutines。从发送方函数启动这些goroutine不是一个选项。这样做很容易,但是,需要学习更复杂的同步技术

等待工人完成的正确方法是什么

已尝试关闭
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还添加了一种使用通道进行同步以备将来参考的方法。谢谢你!我想知道什么更有效…一个完成频道,还是一个等待组…在更复杂的场景中,更容易获得正确的代码