이 코드 조각에서는 goroutine이 시작되고 변수 i를 반복적으로 증가시킵니다.
package main
import "time"
func main() {
i := 1
go func() {
for {
i
}
}()
그러나 출력은 항상 1입니다. 이 동작은 Go 메모리 모델과 이 코드의 특정 구현에 기인할 수 있습니다.
Go 메모리 모델
Go 메모리 모델은 한 고루틴의 변수 읽기가 다른 고루틴의 동일한 변수에 대한 쓰기로 생성된 값을 관찰하도록 보장할 수 있는 조건을 정의합니다. 이는 공유 데이터에 대한 동시 액세스를 위한 동기화의 중요성을 강조합니다.
동기화 생략
주어진 코드에서:
- i에 대한 할당(즉, i ) 동기화 이벤트 뒤에는 변경 사항이 다른 고루틴에 즉시 표시되지 않을 수 있음을 나타내는 동기화 이벤트가 뒤따르지 않습니다.
- 컴파일러는 이 루프 최적화를 무작동으로 단순화하여 최적화할 수 있습니다.
컴파일러에 의한 최적화
공격적인 컴파일러는 i 문을 삭제하여 goroutine을 다음과 같이 효과적으로 줄일 수 있습니다.
for {}
동기화 예시
동기화 부족으로 인해 문제가 발생했음을 입증하려면 다음 코드를 고려하세요.
package main
import (
"sync"
"time"
)
func main() {
mx := new(sync.Mutex)
i := 1
go func() {
for {
mx.Lock()
i
mx.Unlock()
}
}()
이 경우 출력은 예상대로 더 이상 1이 아니라 큰 숫자입니다. sync.Mutex는 동기화를 제공하고 두 goroutine이 제어된 방식으로 i에 액세스하도록 보장하여 goroutine이 i를 증가시키고 변경 사항이 기본 루틴에 표시되도록 합니다.
부인 성명: 제공된 모든 리소스는 부분적으로 인터넷에서 가져온 것입니다. 귀하의 저작권이나 기타 권리 및 이익이 침해된 경우 자세한 이유를 설명하고 저작권 또는 권리 및 이익에 대한 증거를 제공한 후 이메일([email protected])로 보내주십시오. 최대한 빨리 처리해 드리겠습니다.
Copyright© 2022 湘ICP备2022001581号-3