백엔드, 기타/Golang

Golang 4. 동기화 객체(Synchronization)

데브힐러 2020. 8. 25. 08:33
반응형

* 동기화 객체의 종류

  • Mutex
  • RWMutex
  • Cond
  • Once
  • Pool
  • WaitGroup
  • Atomic

 

 

1. 뮤텍스 사용하기

 

 

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())
	var data = []int{} //int형 슬라이스 생

	go func(){
		for i := 0; i<1000; i++{
			data = append(data, 1)
			runtime.Gosched()
			//다른 고루틴이 CPU를 사용할 수 있도록 양보
		}
	}()

	go func() {
		for i := 0; i<1000; i++{
			data = append(data, 1)
			runtime.Gosched()
			//다른 고루틴이 CPU를 사용 할 수 있도록 양보
		}
	}()
	time.Sleep(2 * time.Second)
	fmt.Println((len(data))) //출력값 1779
}

 데이터의 길이가 2000이 아닌 1779가 나왔다. 두 고로틴이 경합을 벌이면서 동시에 data에 접근했기 때문에 app end 함수가 정확하게 처리되지 않은 상황이다.

 이러한 상황을 경쟁 조건(Race condition)이라고 한다.

 

 

 # 데이타 슬라이스를 뮤텍스로 보호하기

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())
	var data = []int{}
	var mutex = new(sync.Mutex)

	go func() {
		for i := 0; i<1000; i++ {
			mutex.Lock()// 뮤텍스 잠금, data슬라이스 보호 시작
			data = append(data, 1)
			mutex.Unlock()
			runtime.Gosched()
		}
	}()

	go func() {
		for i:=0; i<1000; i++ {
			mutex.Lock()
			data = append(data, 1)
			mutex.Unlock()
			runtime.Gosched()
		}
	}()
	time.Sleep(2*time.Second)
	fmt.Println(len(data)) // 2000출력
}

 

 

2. 읽기, 쓰기 뮤텍스 사용하기

 

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())
	var data int = 0
	var rwMutex = new(sync.RWMutex) //읽기, 쓰기 뮤텍스 생성

	go func() {
		for i:=0; i<3; i++ {
			rwMutex.Lock() //쓰기 뮤텍스 잠금, 쓰기 보호 시작
			data += 1 //data에 값 쓰기
			fmt.Println("write :", data)
			time.Sleep(10 * time.Millisecond)
			rwMutex.Unlock() //쓰기 뮤텍스 잠금 해제, 쓰기 보호 종료
		}
	}()

	go func() {
		for i:=0; i<3; i++ {
			rwMutex.RLock() //읽기 뮤텍스 잠금, 읽기 보호 시작
			fmt.Println("read1 :", data)
			time.Sleep(1 * time.Second)
			rwMutex.RUnlock()
		}
	}()

	go func() { //값을 읽는 고루틴
		for i:=0; i<3; i++ {
			rwMutex.RLock()
			fmt.Println("read2 :", data)
			time.Sleep(2 * time.Second)
			rwMutex.RUnlock()
		}
	}()

	time.Sleep(10 * time.Second)
}

 

 

3. 조건변수 사용하기

 

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())
	var mutex = new(sync.Mutex)
	var cond = sync.NewCond(mutex)  //뮤텍스를 이용하여 조건변수 생성
	c := make(chan bool, 3) //비동기 채널

	for i := 0; i < 3; i++ {
		go func(n int) {
			mutex.Lock() //뮤텍스 잠금, cond.Wait()보호 시작
			c <- true
			fmt.Println("wait begin: ", n)
			cond.Wait()
			fmt.Println("wait end: ", n)
			mutex.Unlock()
		}(i)
	}

	for i := 0; i < 3; i++ {
		<-c
	}

	for i := 0; i<3; i++ {
		mutex.Lock() //뮤텍스 잠금, cond.Signal()보호 시작
		fmt.Println("signal: ", i)
		cond.Signal() //대기하고 있는 고루틴 들을 하나씩 깨움
		mutex.Unlock()
	}
	fmt.Scanln()
}

 

 

 


 

 

 

 

 

 

 

 

 

 

 

 

 

반응형