GO · 고루틴/채널
sync.Once & atomic 패키지
한 번만 실행되는 초기화와 원자적 연산으로 동시성을 안전하게 처리합니다.
고루틴/채널고급sync.OnceatomicsingletonCAS동시성
핵심 설명
한 번만 실행되는 초기화와 원자적 연산으로 동시성을 안전하게 처리합니다.
Go code
package main
import (
"fmt"
"sync"
"sync/atomic"
)
// sync.Once — 딱 한 번만 실행 (lazy singleton)
type Database struct {
conn string
}
var (
db *Database
once sync.Once
)
func GetDB() *Database {
once.Do(func() {
fmt.Println("DB 초기화 (한 번만)")
db = &Database{conn: "postgres://localhost:5432/mydb"}
})
return db
}
// atomic — 락 없는 원자적 연산
type AtomicCounter struct {
value int64
}
func (c *AtomicCounter) Inc() {
atomic.AddInt64(&c.value, 1)
}
func (c *AtomicCounter) Load() int64 {
return atomic.LoadInt64(&c.value)
}
func (c *AtomicCounter) CompareAndSwap(old, new int64) bool {
return atomic.CompareAndSwapInt64(&c.value, old, new)
}
func main() {
// sync.Once 테스트
var wg sync.WaitGroup
for i := 0; i < 5; i++ {
wg.Add(1)
go func() {
defer wg.Done()
db := GetDB()
fmt.Println("사용:", db.conn)
}()
}
wg.Wait()
// atomic counter
counter := &AtomicCounter{}
for i := 0; i < 1000; i++ {
wg.Add(1)
go func() {
defer wg.Done()
counter.Inc()
}()
}
wg.Wait()
fmt.Println("최종 카운트:", counter.Load()) // 1000
// CAS (Compare-And-Swap) 패턴
ok := counter.CompareAndSwap(1000, 0)
fmt.Println("CAS 성공:", ok, "값:", counter.Load())
}학습 팁
sync.Once는 초기화 함수가 패닉을 발생시켜도 다시 호출되지 않습니다. 패닉에서 복구해도 초기화는 "완료된" 상태로 남습니다.
주의할 점
atomic 연산은 단일 변수에 대해서만 원자적입니다. 여러 변수를 함께 업데이트해야 하면 Mutex를 사용하세요.
자주 묻는 질문
sync.Once & atomic 패키지란 무엇인가요?
한 번만 실행되는 초기화와 원자적 연산으로 동시성을 안전하게 처리합니다.
sync.Once & atomic 패키지 학습 시 주의할 점은 무엇인가요?
atomic 연산은 단일 변수에 대해서만 원자적입니다. 여러 변수를 함께 업데이트해야 하면 Mutex를 사용하세요.
Continue Learning
Go 학습을 이어가세요
총 200개의 독립 HTML 학습 문서 중 하나입니다. 각 문서는 고유 URL과 canonical 메타데이터를 가집니다.