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
Mary-Kate Olsenasal
2024-12-25 04:21:09542semak imbas

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
}

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 {}
}

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 {}
}

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!

Kenyataan:
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