Rumah > pembangunan bahagian belakang > Golang > Bagaimanakah Saya Boleh Menghalang Perlumbaan Data Apabila Membaca dan Menulis Go Structs serentak?

Bagaimanakah Saya Boleh Menghalang Perlumbaan Data Apabila Membaca dan Menulis Go Structs serentak?

Mary-Kate Olsen
Lepaskan: 2024-12-25 04:21:09
asal
555 orang telah melayarinya

How Can I Prevent Data Races When Concurrently Reading and Writing Go Structs?

Baca dan Tulis Serentak Struktur Go Tanpa Penguncian Eksplisit

Akses serentak kepada data kongsi dalam Go boleh menjadi sumber kemungkinan ralat, seperti perlumbaan data. Apabila akses kepada struktur data adalah serentak, iaitu berbilang goroutine boleh mengaksesnya pada masa yang sama, adalah penting untuk memastikan bahawa data dibaca dan ditulis dalam cara yang disegerakkan untuk mengelakkan ketidakkonsistenan.

Akses Serentak kepada Struktur

Pertimbangkan struct Go berikut Metadata:

type Metadata struct {
    mu  sync.RWMutex // ?
    key bool
}
Salin selepas log masuk

Seperti yang kita lihat, struct Metadata mengandungi kunci medan jenis bool dan satu lagi medan mu jenis penyegerakan.RWMutex, iaitu pelaksanaan kunci baca-tulis.

Perlumbaan Data dalam Struktur

Jika kami mencipta tika Metadata dan membenarkan berbilang gorout dibaca serentak dan tulis medannya, kita mungkin menghadapi perlumbaan data. Perlumbaan data berlaku apabila berbilang gorout mengakses data yang sama secara serentak dan sekurang-kurangnya satu daripada mereka menjalankan operasi tulis.

Kod berikut menunjukkan akses baca dan tulis serentak kepada struct Metadata tanpa penguncian yang jelas:

func concurrentStruct() {
    m := new(Metadata)

    for i := 0; i < 100000; i++ {
        go func(metadata *Metadata) {
            for {
                readValue := metadata.key
                if readValue {
                    metadata.key = false
                }
            }
        }(m)

        go func(metadata *Metadata) {
            for {
                metadata.key = true
            }
        }(m)
    }

    select {}
}
Salin selepas log masuk

Dalam kod ini, kami mencipta goroutine yang membaca dan menulis medan kunci secara serentak. Kami menggunakan pernyataan pilih untuk menyekat goroutine utama, membenarkan goroutine serentak berjalan. Menggunakan arahan go run -race untuk menjalankan program, kita akan mendapat amaran yang menunjukkan DATA RACE.

Walau bagaimanapun, program ini terus berjalan tanpa ranap. Ini kerana masa jalan Go mempunyai semakan serentak terbina dalam, tetapi ia tidak menjamin pelaksanaan yang selamat. Dalam kes ini, perlumbaan data boleh membawa kepada tingkah laku yang tidak ditentukan dan hasil yang tidak betul.

Menyelesaikan Perlumbaan Data dalam Struktur

Untuk mengelakkan perlumbaan data apabila membaca dan menulis pada struct serentak, kita perlu menggunakan yang betul mekanisme penguncian. Satu cara ialah menggunakan mutex, seperti yang ditunjukkan dalam kod berikut:

func concurrentStructWithMuLock() {
    m := new(Metadata)

    go func(metadata *Metadata) {
        for {
            metadata.mu.Lock()
            readValue := metadata.key
            if readValue {
                metadata.key = false
            }
            metadata.mu.Unlock()
        }
    }(m)

    go func(metadata *Metadata) {
        for {
            metadata.mu.Lock()
            metadata.key = true
            metadata.mu.Unlock()
        }
    }(m)

    select {}
}
Salin selepas log masuk

Dalam kod ini, kami telah menambah kunci baca-tulis pada struct Metadata dan menggunakan mu.Lock() dan mu. Buka kunci() untuk menyegerakkan akses kepada medan kunci. Menjalankan program dengan go run -race tidak akan menjana sebarang amaran lagi, menunjukkan bahawa tiada perlumbaan data.

Atas ialah kandungan terperinci Bagaimanakah Saya Boleh Menghalang Perlumbaan Data Apabila Membaca dan Menulis Go Structs serentak?. 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