AtomicStoreUint32와 Sync.Once의 할당
Go의 sync.Once 유형에 대한 소스 코드를 탐색하는 동안 사용법에 관한 질문이 생깁니다. done 플래그 설정을 위한 일반 할당과 비교하여atom.StoreUint32.
잘못된 구현:
원본 소스 코드에 잘못된 구현이 포함되어 있습니다:
<code class="go">func (o *Once) Do(f func()) { if atomic.CompareAndSwapUint32(&o.done, 0, 1) { f() } }</code>
이 구현은 함수가 반환될 때 f가 완료된다는 것을 보장하지 못합니다. 첫 번째 호출이 완료되었다고 가정하면 동시 호출을 통해 승자가 f를 실행하는 동안 두 번째 호출자가 즉시 반환될 수 있지만, 그렇지 않을 수도 있습니다.
올바른 구현:
이 문제를 해결하기 위해 현재 구현에서는 뮤텍스와 함께omic.StoreUint32를 사용합니다.
<code class="go">func (o *Once) Do(f func()) { if atomic.LoadUint32(&o.done) == 0 { o.doSlow(f) } }</code>
<code class="go">func (o *Once) doSlow(f func()) { o.m.Lock() defer o.m.Unlock() if o.done == 0 { defer atomic.StoreUint32(&o.done, 1) f() } }</code>
왜 AtomicStoreUint32를 사용하나요?
atomic의 사용 .StoreUint32는 f가 완료된 후 다른 고루틴이 o.done에 대한 변경 사항을 관찰할 수 있도록 보장하는 데 필요합니다. 기본 할당은 특정 아키텍처에서 원자적일 수 있지만 Go의 메모리 모델은 지원되는 모든 아키텍처에서 원자적 작업을 보장하기 위해 원자 패키지를 사용해야 합니다.
완료 플래그에 대한 액세스:
목표는 완료 플래그에 대한 액세스가 뮤텍스 외부에서 안전하게 이루어지도록 하는 것입니다. 따라서 뮤텍스로 잠그는 대신 원자 연산이 활용됩니다. 이러한 최적화는 트래픽이 많은 시나리오에 sync.Once를 배포할 수 있도록 하여 빠른 경로의 효율성을 향상시킵니다.
doSlow용 뮤텍스:
doSlow 내의 뮤텍스는 다음을 보장합니다. o.done이 설정되기 전에 단 한 명의 호출자만이 f를 실행합니다. Atomic.StoreUint32는 뮤텍스의 임계 섹션 외부에서omic.LoadUint32와 동시에 발생할 수 있기 때문에 플래그를 작성하는 데 사용됩니다.
동시 쓰기 대 읽기:
직접 읽기 o.done in doSlow는 뮤텍스 보호로 인해 안전합니다. 또한 o.done을omic.LoadUint32와 동시에 읽는 것은 두 작업 모두 읽기만 포함하므로 안전합니다.
위 내용은 `sync.Once`가 `done` 플래그에 대한 일반 할당 대신 `atomic.StoreUint32`를 사용하는 이유는 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!