Rumah >pembangunan bahagian belakang >Golang >Bagaimana untuk Mengelakkan Perlumbaan Data Semasa Melancarkan Goroutine dalam Go?

Bagaimana untuk Mengelakkan Perlumbaan Data Semasa Melancarkan Goroutine dalam Go?

Mary-Kate Olsen
Mary-Kate Olsenasal
2024-12-08 17:37:11187semak imbas

How to Avoid Data Races When Launching Goroutines in Go?

Perlumbaan Data dalam Rutin Pergi Serentak

Kod ini menunjukkan isu perlumbaan data dalam rutin Go serentak:

package main

import (
    "fmt"
    "time"
)

type field struct {
    name string
}

func (p *field) print() {
    fmt.Println(p.name)
}

func main() {
    data := []field{{"one"}, {"two"}, {"three"}}
    for _, v := range data {
        go v.print()
    }
    <-time.After(1 * time.Second)
}

Isu:

Kod dicetak "tiga" tiga kali dan bukannya mencetak "satu", "dua", dan "tiga" dalam sebarang susunan. Ini kerana terdapat perlumbaan data.

Penjelasan:

Secara tersirat, kod mengambil alamat pembolehubah v apabila menilai hujah kepada fungsi goroutine. Fungsi goroutine v.print() adalah bersamaan dengan (&v).print(). Gelung menukar nilai v dan apabila goroutine dilaksanakan, gelung tersebut mempunyai nilai terakhir gelung ("tiga").

Pembetulan:

Terdapat beberapa cara untuk membetulkan perlumbaan data ini:

  • Buat pembolehubah baharu dalam gelung:
for _, v := range data {
    v := v        // short variable declaration of new variable `v`.
    go v.print()
}
  • Gunakan sepotong penunjuk:
data := []*field{{"one"}, {"two"}, {"three"}} // note '*'
for _, v := range data {
    go v.print()
}
  • Gunakan alamat kepingan elemen:
data := []field{{"one"}, {"two"}, {"three"}} // note '*'
for i := range data {
    v := &data[i]
    go v.print()
}
  • Lepasi pembolehubah julat sebagai hujah kepada fungsi tanpa nama:
for _, v := range data {
  go func(v field) {
    v.print() // take address of argument v, not range variable v.
  }(v)
}

Atas ialah kandungan terperinci Bagaimana untuk Mengelakkan Perlumbaan Data Semasa Melancarkan Goroutine dalam Go?. 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