Mengapakah Melampirkan pada Slice dalam Goroutine Serentak Tidak Selamat Benang?

Linda Hamilton
Lepaskan: 2024-11-10 00:49:02
asal
733 orang telah melayarinya

Why is Appending to a Slice in Concurrent Goroutines Not Thread-Safe?

Kepingan Serentak: Tambah Tidak Selamat Benang

Soalan:

Pertimbangkan kod berikut yang ditambahkan pada kepingan menggunakan berbilang goroutine dalam satu untuk gelung:

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()
Salin selepas log masuk

Sesekali, kod ini menghasilkan data yang hilang atau kosong dalam destSlice atau tidak termasuk semua elemen daripada sourceSlice. Mengapa ini mungkin berlaku?

Jawapan:

Dalam Go, semua nilai terdedah kepada perlumbaan data apabila tertakluk pada operasi baca/tulis serentak, termasuk kepingan. Ini disebabkan oleh cara pengepala slice (yang mengandungi maklumat tentang kapasiti dan panjang kepingan) dilaksanakan.

Menjalankan kod dengan bendera -race akan mengesahkan kehadiran perlumbaan data:

go run -race play.go
Salin selepas log masuk

Penyelesaian:

Untuk mengelakkan perlumbaan data dan memastikan keselamatan serentak apabila disertakan pada slice, primitif penyegerakan seperti penyegerakan.Mutex hendaklah digunakan untuk menjaga penulisan nilai 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()
Salin selepas log masuk

Sebagai alternatif, pertimbangkan untuk menggunakan saluran untuk memudahkan proses penambahan serentak.

Atas ialah kandungan terperinci Mengapakah Melampirkan pada Slice dalam Goroutine Serentak Tidak Selamat Benang?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:php.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Artikel terbaru oleh pengarang
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan