>  기사  >  백엔드 개발  >  `sync.Once`가 `done` 플래그에 대한 일반 할당 대신 `atomic.StoreUint32`를 사용하는 이유는 무엇입니까?

`sync.Once`가 `done` 플래그에 대한 일반 할당 대신 `atomic.StoreUint32`를 사용하는 이유는 무엇입니까?

Barbara Streisand
Barbara Streisand원래의
2024-10-31 05:40:01677검색

Why does `sync.Once` use `atomic.StoreUint32` instead of a regular assignment for the `done` flag?

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 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.