GoLang의 sync.WaitGroup 사용법 소개

2701 단어 GoLang
소개하다.
다음과 같은 코드가 자주 표시됩니다.
package main

import (
    "fmt"
    "time"
)

func main(){
    for i := 0; i < 100 ; i++{
        go fmt.Println(i)
    }
    time.Sleep(time.Second)
}

주 스레드는goroutine가 모두 실행되기를 기다리기 위해 프로그램의 끝에 time.Sleep()를 사용하여 일정 시간 수면을 취하고 다른 스레드가 충분히 실행되기를 기다려야 한다.간단한 코드에 대해 100개의 for 순환을 1초 안에 실행할 수 있고 time.Sleep()도 원하는 효과를 얻을 수 있다.
그러나 실제 생활의 대다수 장면에 있어 1초는 부족하고 대부분의 경우 우리는 for순환 내 코드의 운행 시간의 장단을 예측할 수 없다.이때 time.Sleep()를 사용하여 대기 작업을 완성할 수 없습니다.
파이프를 사용하여 이러한 작업을 완료하는 것을 고려할 수 있습니다.
func main() {
    c := make(chan bool, 100)
    for i := 0; i < 100; i++ {
        go func(i int) {
            fmt.Println(i)
            c 

우선 파이프를 사용하는 것이 우리의 목적을 달성할 수 있을 뿐만 아니라 목적을 달성할 수 있을 뿐만 아니라 매우 완벽하게 목적을 달성할 수 있다는 것을 확신할 수 있다.
그러나 파이프는 이곳에서 약간의 대재소용으로 보인다. 왜냐하면 이것은 단순히 동기화 처리만 하는 것이 아니라, 여기서 파이프를 사용하는 것은 사실상 적합하지 않기 때문이다.그리고 만약에 우리가 1만, 10만, 심지어 더 많은 for순환을 가지고 있다고 가정해도 같은 수량의 파이프를 신청해야 하며 메모리에 대한 비용도 적지 않다.
이런 상황에 대해 go언어에는 다른 도구sync.WaitGroup가 있어 우리가 이 목적을 달성하는 데 더욱 편리하게 도움을 줄 수 있다.WaitGroup 대상 내부에 계수기가 하나 있는데 처음에는 0부터 세 가지 방법이 있다. Add(), Done(), Wait() 계수기의 수량을 조절하는 데 쓰인다.Add(n) 계수기를 n로 설정하고Done() 매번 계수기-1를 설정하면 wait()는 코드의 운행을 막아 계수기의 땅값이 0으로 줄어들 때까지 막는다.WaitGroup를 사용하여 위 코드를 다음과 같이 수정할 수 있습니다.
func main() {
    wg := sync.WaitGroup{}
    wg.Add(100)
    for i := 0; i < 100; i++ {
        go func(i int) {
            fmt.Println(i)
            wg.Done()
        }(i)
    }
    wg.Wait()
}

여기에 우선 wg계수를 100으로 설정하고 모든 for 순환이 끝나면 계수기를 1로 줄이고 주 함수에서 Wait()wg가 0이 될 때까지 막는다. 즉 모든 100개의 for 순환이 끝날 때까지 막는다.파이프를 사용하는 것보다 WaitGroup 훨씬 가볍다.
주의 사항
1. 카운터는 음수가 될 수 없습니다.Add()를 사용하여 wg에 마이너스 값을 설정할 수 없습니다. 그렇지 않으면 코드가 잘못 보고됩니다.
panic: sync: negative WaitGroup counter

goroutine 1 [running]:
sync.(*WaitGroup).Add(0xc042008230, 0xffffffffffffff9c)
    D:/Go/src/sync/waitgroup.go:75 +0x1d0
main.main()
    D:/code/go/src/test-src/2-Package/sync/waitgroup/main.go:10 +0x54

같은 사용Done()도 계수기를 음수로 설정하지 않도록 각별히 주의해야 한다.
2. WaitGroup 객체는 참조 유형이 아닙니다.
WaitGroup 객체는 참조 유형이 아니므로 함수를 통해 값을 전달할 때 주소를 사용해야 합니다.
func main() {
    wg := sync.WaitGroup{}
    wg.Add(100)
    for i := 0; i < 100; i++ {
        go f(i, &wg)
    }
    wg.Wait()
}

//          ,           
func f(i int, wg *sync.WaitGroup) { 
    fmt.Println(i)
    wg.Done()
}

좋은 웹페이지 즐겨찾기