Rumah >pembangunan bahagian belakang >Golang >Mengapakah fungsi `tambah` tidak selamat benang untuk akses serentak dalam Go?
Tambah Fungsi: Tidak Selamat Benang untuk Akses Serentak
Apabila menggunakan goroutine secara serentak untuk menambahkan elemen pada kepingan dalam gelung for, anomali dalam data boleh timbul. Data yang hilang atau kosong mungkin muncul dalam kepingan terhasil, menunjukkan perlumbaan data yang berpotensi.
Ini berlaku kerana dalam Go, tiada nilai yang secara semula jadi selamat untuk membaca dan menulis serentak. Kepingan, yang diwakili oleh pengepala kepingan, tidak terkecuali. Kod yang diberikan mempamerkan perlumbaan data kerana akses serentak:
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()
Untuk mengesahkan kehadiran perlumbaan data, laksanakan arahan berikut:
go run -race play.go
Output akan memaklumkan anda tentang perlumbaan data :
WARNING: DATA RACE ...
Menyelesaikan Isu Konkurensi
Untuk menyelesaikan isu ini, lindungi akses tulis kepada destSlice dengan menggunakan penyegerakan.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()
Sebagai alternatif, pertimbangkan untuk menggunakan saluran untuk mengendalikan lampiran secara tidak segerak:
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()
Atas ialah kandungan terperinci Mengapakah fungsi `tambah` tidak selamat benang untuk akses serentak dalam Go?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!