>백엔드 개발 >Golang >Go의 동시 액세스에 대해 `append` 함수가 스레드로부터 안전하지 않은 이유는 무엇입니까?

Go의 동시 액세스에 대해 `append` 함수가 스레드로부터 안전하지 않은 이유는 무엇입니까?

Patricia Arquette
Patricia Arquette원래의
2024-11-10 03:50:02369검색

Why is `append` function not thread-safe for concurrent access in Go?

추가 함수: 동시 액세스에 대해 스레드로부터 안전하지 않음

for 루프 내의 슬라이스에 요소를 추가하기 위해 고루틴을 동시에 사용할 때 예외가 발생합니다. 데이터에서 발생할 수 있습니다. 누락되거나 빈 데이터가 결과 조각에 나타날 수 있으며 이는 잠재적인 데이터 경합을 나타냅니다.

이는 Go에서는 동시 읽기 및 쓰기에 본질적으로 안전한 값이 없기 때문에 발생합니다. 슬라이스 헤더로 표시되는 슬라이스도 예외는 아닙니다. 제공된 코드는 동시 액세스로 인해 데이터 경합을 나타냅니다.

destSlice := make([]myClass, 0)

var wg sync.WaitGroup
for _, myObject := range sourceSlice {
    wg.Add(1)
    go func(closureMyObject myClass) {
        defer wg.Done()
        var tmpObj myClass
        tmpObj.AttributeName = closureMyObject.AttributeName
        destSlice = append(destSlice, tmpObj)
    }(myObject)
}
wg.Wait()

데이터 경합이 있는지 확인하려면 다음 명령을 실행합니다.

go run -race play.go

출력에서는 데이터 경합에 대해 경고합니다. :

WARNING: DATA RACE
...

동시성 해결 문제

이 문제를 해결하려면 sync.Mutex를 사용하여 destSlice에 대한 쓰기 액세스를 보호하세요.

var (
    mu        = &sync.Mutex{}
    destSlice = make([]myClass, 0)
)

var wg sync.WaitGroup
for _, myObject := range sourceSlice {
    wg.Add(1)
    go func(closureMyObject myClass) {
        defer wg.Done()
        var tmpObj myClass
        tmpObj.AttributeName = closureMyObject.AttributeName
        mu.Lock()
        destSlice = append(destSlice, tmpObj)
        mu.Unlock()
    }(myObject)
}
wg.Wait()

또는 채널을 사용하여 추가를 비동기적으로 처리하는 것을 고려해 보세요.

var (
    appendChan = make(chan myClass)
    destSlice  = make([]myClass, 0)
)

var wg sync.WaitGroup
for _, myObject := range sourceSlice {
    wg.Add(1)
    go func(closureMyObject myClass) {
        defer wg.Done()
        var tmpObj myClass
        tmpObj.AttributeName = closureMyObject.AttributeName
        appendChan <- tmpObj
    }(myObject)
}
go func() {
    for {
        tmpObj := <-appendChan
        destSlice = append(destSlice, tmpObj)
    }
}()
wg.Wait()

위 내용은 Go의 동시 액세스에 대해 `append` 함수가 스레드로부터 안전하지 않은 이유는 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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