Append는 정말 스레드로부터 안전한가요?
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()
-race 옵션을 사용하여 이 코드 실행 여러 데이터 경합이 드러납니다. 이러한 경합을 방지하려면 뮤텍스와 같은 동기화 메커니즘을 사용해야 합니다. 다음은 뮤텍스를 사용하여 수정된 코드 조각입니다.
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()
대체 솔루션은 고루틴이 추가할 값을 보내는 채널을 사용하는 것입니다. 전용 고루틴은 이러한 값 수신을 처리하고 추가 작업을 수행할 수 있습니다.
요약하자면, 슬라이스 요소는 고유한 변수이고 동기화 없이 동시에 액세스할 수 있지만, 슬라이스 헤더는 동시 추가 작업 중에 데이터 경합을 방지하기 위해 동기화가 필요합니다.
위 내용은 Go 루틴과 함께 사용할 때 Go의 추가가 스레드로부터 안전합니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!