Go by Example: 원자성 카운터

Go에서 상태를 관리하는 가장 기본적인 메커니즘은 채널을 통한 통신입니다. 이는 worker pools 예제에서 보았습니다. Go에는 상태를 관리하기 위한 몇 가지 방법이 더 있습니다. 이번 예제에선 여러개의 고루틴에서 접근되는 원자성 카운터(atomic counters)를 위한 sync/atomic 패키지를 사용하여 살펴보겠습니다.

package main
import "fmt"
import "time"
import "sync/atomic"
func main() {

(항상 양수인) 카운터를 나타내기 위해 부호 없는 정수를 사용합니다.

	var ops uint64 = 0

동시 업데이트를 시뮬레이션 하기 위해, 1 밀리초마다 카운터를 증가시키는 고루틴을 50개 띄웁니다.

	for i := 0; i < 50; i++ {
		go func() {
			for {

카운터를 원자적으로 증가시키기 위해 ops 카운터의 메모리 주소를 전달하여 AddUint64를 사용합니다.

				atomic.AddUint64(&ops, 1)

증가 사이를 조금 대기합니다.

				time.Sleep(time.Millisecond)
			}
		}()
	}

ops가 누적될 수 있도록 1초간 대기합니다.

	time.Sleep(time.Second)

카운터가 다른 고루틴에 의해 증가되는 도중에 카운터를 안전하게 사용하기위해, LoadUint64를 사용하여 현재값의 복사본을 opsFinal로 가져옵니다. 위에서도 보았듯이 값을 페치하기 위해 &ops의 메모리 주소를 전달합니다.

	opsFinal := atomic.LoadUint64(&ops)
	fmt.Println("ops:", opsFinal)
}

프로그램을 실행하면 약 40,000번의 연산이 실행되었음을 보여줍니다.

$ go run atomic-counters.go
ops: 41419

다음 장에선 상태를 관리하는 또 다른 도구인 뮤텍스를 살펴보겠습니다.

다음 예제: 뮤텍스.