세 번째 고루틴에서 두 고루틴의 완료 상태를 추적하기 위한 Golang의 모범 사례는 무엇입니까? Golang에서 두 고루틴의 완료 상태를 추적하고 그 결과를 세 번째 고루틴에서 처리하려면 동기화 패키지에서 WaitGroup을 사용하는 것이 가장 좋습니다. WaitGroup을 사용하면 다른 고루틴이 완료될 때까지 기본 고루틴에서 기다릴 수 있습니다. 먼저, WaitGroup 개체를 생성하고 기본 고루틴에서 Add 메서드를 호출하여 대기 중인 고루틴 수를 설정해야 합니다. 그런 다음 각 고루틴이 끝날 때 Done 메서드가 호출되어 해당 고루틴의 완료를 알립니다. 마지막으로 세 번째 고루틴에서는 Wait 메소드가 호출되어 모든 고루틴이 완료될 때까지 기다립니다. 이런 방식으로 우리는 두 고루틴의 결과를 안전하게 추적하고 처리할 수 있습니다. 이는 여러 고루틴의 완료 상태를 추적하기 위한 Golang의 모범 사례입니다.
3개의 고루틴이 동시에 실행되고 있습니다. 그 중 두 개는 처리를 수행하고 결과를 결과 채널로 보냅니다. 세 번째 고루틴은 결과 채널을 읽어 결과를 "계산"합니다. 대기 그룹을 사용하여 두 계산 고루틴이 완료될 때까지 기다린 다음 결과 채널을 반복하여 결과를 계산할 수 있지만 이는 확장되지 않으며 엄청난 버퍼 크기로 버퍼링된 결과 채널을 만들어야 하는데 이는 허용되지 않습니다. 프로덕션 코드에서.
처리가 진행되는 동안 결과를 계산하고 싶지만 모든 계산이 완료되기 전에 프로그램을 종료하고 싶지 않습니다. Go에서 이를 달성하기 위한 모범 사례는 무엇입니까?
이것이 현재 제가 사용하는 방법이며 훌륭하게 작동합니다. 조금 투박해 보이는데 더 좋은 방법이 있는지 궁금합니다.
package main import ( "fmt" "sync" ) type T struct{} func main() { var widgetInventory int = 1000 transactions := make(chan int, 100) salesDone := make(chan T) purchasesDone := make(chan T) var wg sync.WaitGroup fmt.Println("Starting inventory count = ", widgetInventory) go makeSales(transactions, salesDone) go newPurchases(transactions, purchasesDone) wg.Add(1) go func() { salesAreDone := false purchasesAreDone := false for { select { case transaction := <-transactions: widgetInventory += transaction case <-salesDone: salesAreDone = true case <-purchasesDone: purchasesAreDone = true default: if salesAreDone && purchasesAreDone { wg.Done() return } } } }() wg.Wait() fmt.Println("Ending inventory count = ", widgetInventory) } func makeSales(transactions chan int, salesDone chan T) { for i := 0; i < 3000; i++ { transactions <- -100 } salesDone <- struct{}{} } func newPurchases(transactions chan int, purchasesDone chan T) { for i := 0; i < 3000; i++ { transactions <- 100 } purchasesDone <- struct{}{} }
은 어떤 합리적인 정의괜찮아에 맞지 않습니다. 여기에 인기 있는 for
루프가 있습니다:
읽을 채널이 없으면 default
사건이 실행됩니다. 채널이 작동하는 방식 때문에 이런 일이 많이 발생합니다.
약간 수정된 코드 버전은 이 루프의 "열"을 보여줍니다. 정확한 결과는 다양하며 상당히 높을 수 있습니다.
으아악기본값이 채널의 항목을 차단하지 않는 한 채널에서 선택
할 때 select
ing 来自通道时,您不希望出现 default
사례를 원하지 않습니다. 그렇지 않으면 이와 같은 열 순환이 발생합니다.
nil
가능한 채널을 사용 일반적으로 선택 항목에서 닫힌 채널을 식별하고 채널 변수를 nil
; select
永远不会成功地从 nil
select
는 채널에서 성공적으로 읽히지 않으므로 선택 항목이 효과적으로 "비활성화"됩니다.
코드의 수정된 버전을 고려해보세요: salesDone
和 purchasesDone
都被“发出信号”,我们 close(transactions)
。一旦我们耗尽 transactions
并且它被关闭,我们将 transactions
设置为 nil。我们在 transactions
不为 nil 时循环,在这段代码中,意味着所有通道都是 nil
으아악
salesDone
과 purchasesDone
이 모두 "신호"되면 거래를 종료
합니다. 트랜잭션
을 소진하고 main
共享范围。否则,将 transactions
设置为 nil
将写入一个在 goroutine 之间共享的变量。然而在这种情况下,无论如何,这并不重要,因为我们“知道”我们是最后一个从 transactions
종료되면 트랜잭션
을 nil로 설정합니다. transactions
가 nil이 아닐 때 반복합니다. 이는 이 코드에서 모든 채널이
main
과 범위를 공유하지 않습니다. 그렇지 않은 경우 transactions
를 로 설정하면 고루틴 간에 공유되는 변수에 기록됩니다. 그러나 이 경우에는 우리가 트랜잭션
에서 마지막으로 읽은 것임을 "알기" 때문에 어쨌든 문제가 되지 않습니다. transactions
的生产。然后你想排空 transactions
。一旦通道关闭并排空,main
select
来执行此操作。而 select
여기서 무엇을 하고 있는지 생각해보면 두 프로듀서가 페어링을 완료할 때까지 기다려야
각 "작업자"에 대한 케이스를 🎜 가질 필요는 없습니다. 이는 꽤 우아하지 않은 일이지만, 여러 작업자를 하드코딩하고 "완료" 채널을 개별적으로 처리해야 합니다. 🎜 🎜당신이 해야 할 일은:🎜
var resultswgsync.WaitGroup
之外,还为消费者添加一个。defer wg.Done()
defer resultswg.Done()
在遍历 transactions
之前:
go func() { defer resultswg.Done() for transaction := range transactions { widgetInventory += transaction } }()
wg.Wait() close(transactions) resultswg.Wait()
package main import ( "fmt" "sync" ) func main() { var widgetInventory int = 1000 transactions := make(chan int, 100) var wg, resultswg sync.WaitGroup fmt.Println("Starting inventory count = ", widgetInventory) wg.Add(2) go makeSales(transactions, &wg) go newPurchases(transactions, &wg) resultswg.Add(1) go func() { defer resultswg.Done() for transaction := range transactions { widgetInventory += transaction } }() wg.Wait() close(transactions) resultswg.Wait() fmt.Println("Ending inventory count = ", widgetInventory) } func makeSales(transactions chan int, wg *sync.WaitGroup) { defer wg.Done() for i := 0; i < 3000; i++ { transactions <- -100 } } func newPurchases(transactions chan int, wg *sync.WaitGroup) { defer wg.Done() for i := 0; i < 3000; i++ { transactions <- 100 } }
您可以在这里看到,在此模式中可以有任意数量的生产者;您只需为每个生产者添加 wg.Add(1)
即可。
当我不知道每个工作人员会返回多少结果时,我一直使用这种模式来并行化工作。我发现它很容易理解,并且比尝试 select
多个通道简单得多。事实上,我什至想说,如果您发现自己从多个渠道进行 select
ing,您应该退后一步,确保它对您来说确实有意义。我使用 select
的频率远远低于使用等待组的频率。
위 내용은 세 번째 고루틴 내에서 두 고루틴의 완료 상태를 추적하기 위한 Golang의 모범 사례는 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!