본문 바로가기
IT 초보코딩의 세계/Go 언어

Go언어의 WaitGroup 와 원자적 연산법 4장

by 조이럭키7 2023. 4. 5.
반응형

앞서서 조건변수 그리고 Once 사용법, Pool을 포스팅하였고 보지못했다면 아래 포스팅을 눌러 보도록하자

https://joylucky7.tistory.com/35

 

Go언어의 조건변수, Once 사용법, Pool 구조체 3장

앞서서 채널과 Select구문 그리고 Sync 를 보지 않았다면 아래 포스팅을 숙지후에 3장을 보도록 하자 https://joylucky7.tistory.com/34 Go언어의 채널(Channel), Select 구문, Sync 패키지 2장 동시성과 고루틴, 데

joylucky7.tistory.com


◆ WaitGroup

대기 그룹은 고루틴이 모두 끝날 때까지 기다릴 때 사용

time.Sleep, fmt. Scanln 함수를 사용하여 고루틴이 끝날 때까지 임시로 대기했는데 대기 그룹을 사용하여 고루틴이 끝날 때까지 기다릴 수 있음

대기 그룹의 구조체와 함수

    ● sync.WaitGroup

    ● func (wg *WaitGroup) Add(delta int): 대기 그룹에 고루틴 개수 추가

    ● func (wg *WaitGroup) Done( ):고루틴이 끝났다는 것을 알려줄 때 사용

    ● func (wg *WaitGroup) Wait(): 모든 고루틴이 끝날 때까지 기다림

package main

import (
  "fmt"
  "runtime"
  "sync"
)

func main() {
  runtime.GOMAXPROCS(runtime.NumCPU()) // 모든 CPU 사용

  wg := new(sync.WaitGroup) // 대기 그룹 생성

  for i := 0; i < 10; i++ {
  wg.Add(1)            // 반복할 때마다 wg.Add 함수로 1씩 추가
  go func(n int) {     // 고루틴 10개 생성
  fmt.Println(n)
  wg.Done()    // 고루틴이 끝났다는 것을 알려줌
  }(i)
  }

  wg.Wait() // 모든 고루틴이 끝날 때까지 기다림
  fmt.Println("the end")
}

◆ 원자적 연산

더 이상 분해되지 않아야 하는 연산을 해야 할 때 사용

sync/atomic 패키지의 함수 이용

atomic 연산의 종류

    ● Add 계열: 변수에 값을 더하고 결과를 리턴

    ● CompareAndSwap 계열: 변수 AB 비교하여 같으면 C 대입하고 AB가 같으면 true 다르면 false 리턴

    ● Load 계열: 변수에서 값을 가져옴

    ● Store계열: 변수에 값을 저장

    ● Swap 계열: 변수에 새 값을 대입하고 이전 값을 리턴

atomic 연산을 적용하지 않은 경우

package main

import (
  "fmt"
  "runtime"
  "sync"
)

func main() {
  runtime.GOMAXPROCS(runtime.NumCPU()) // 모든 CPU 사용
  var data int32 = 0
  wg := new(sync.WaitGroup)
  for i := 0; i < 2000; i++ {
  wg.Add(1)
  go func() {       // 고루틴 2,000개 생성
  data += 1 // 1씩 더함
  wg.Done()
  }()
  }
  for i := 0; i < 1000; i++ {
  wg.Add(1)
  go func() {       // 고루틴 1,000개 생성
  data -= 1 // 1씩 뺌
  wg.Done()
  }()
  }
  wg.Wait()
  fmt.Println(data)
}

 atomic 연산을 적용한 경우

package main

import (
  "fmt"
  "runtime"
  "sync"
  "sync/atomic"
)

func main() {
  runtime.GOMAXPROCS(runtime.NumCPU()) // 모든 CPU 사용

  var data int32 = 0
  wg := new(sync.WaitGroup)

  for i := 0; i < 2000; i++ {
  wg.Add(1)
  go func() {                       // 고루틴 2,000개 생성
  atomic.AddInt32(&data, 1) // 원자적 연산으로 1씩 더함
  wg.Done()
  }()
  }

  for i := 0; i < 1000; i++ {
  wg.Add(1)
  go func() {                        // 고루틴 1,000개 생성
  atomic.AddInt32(&data, -1) // 원자적 연산으로 1씩 뺌
  wg.Done()
  }()
  }

  wg.Wait()
  fmt.Println(data)
}

 

반응형

댓글