추가 함수: 동시 액세스에 대해 스레드로부터 안전하지 않음
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:
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
부인 성명: 제공된 모든 리소스는 부분적으로 인터넷에서 가져온 것입니다. 귀하의 저작권이나 기타 권리 및 이익이 침해된 경우 자세한 이유를 설명하고 저작권 또는 권리 및 이익에 대한 증거를 제공한 후 이메일([email protected])로 보내주십시오. 최대한 빨리 처리해 드리겠습니다.
Copyright© 2022 湘ICP备2022001581号-3