Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Analisis perangkap WaitGroup Golang dan selesaikan masalah

Analisis perangkap WaitGroup Golang dan selesaikan masalah

藏色散人
藏色散人ke hadapan
2021-09-14 15:57:021978semak imbas

Artikel ini diperkenalkan kepada anda melalui lajur go language tentang perangkap WaitGroup Golang, saya harap ia dapat membantu rakan yang memerlukan.

sync.WaitGroup ialah struktur data yang sangat biasa digunakan dalam persekitaran serentak, digunakan untuk menunggu tamatnya semua coroutine menulis kod, saya hanya mengikuti contoh, dan saya tidak perlu mendalami penggunaannya. Beberapa hari yang lalu, saya tertanya-tanya sama ada saya boleh melaksanakan fungsi Add() dalam coroutine Jawapannya adalah tidak.

Perangkap terletak pada urutan panggilan bagi tiga fungsi WaitGroup. Mari kita semak dahulu fungsi tiga fungsi:

  1. Add(delta int): Tambahkan delta ke kaunter, contohnya, naikkan 1 apabila memulakan coroutine.
  2. Done(): Dilaksanakan sebelum coroutine keluar, kurangkan kaunter sebanyak 1.
  3. Wait(): Kaunter menunggu yang menyekat ialah 0.

Lakukan ujian

Atur cara berikut mencipta bapa coroutine, dan kemudian coroutine bapa mencipta 10 sub-coroutine Fungsi utama menunggu semua coroutine selesai dan kemudian keluar. Lihat Lihat jika terdapat apa-apa yang salah dengan kod di bawah?

package main

import (
    "fmt"
    "sync"
)

func father(wg *sync.WaitGroup) {
    wg.Add(1)
    defer wg.Done()

    fmt.Printf("father\n")
    for i := 0; i < 10; i++ {
        go child(wg, i)
    }
}

func child(wg *sync.WaitGroup, id int) {
    wg.Add(1)
    defer wg.Done()

    fmt.Printf("child [%d]\n", id)
}

func main() {
    var wg sync.WaitGroup
    go father(&wg)

    wg.Wait()
    log.Printf("main: father and all chindren exit")
}

Adakah anda menemui masalahnya? Jika anda tidak melihat hasil berjalan berikut: fungsi utama mula tamat sebelum sub-coroutine tamat.

father
main: father and all chindren exit
child [9]
child [0]
child [4]
child [7]
child [8]

Analisis Perangkap

Sebab bagi masalah di atas ialah fungsi Add() dilaksanakan dalam coroutine selepas coroutine dicipta, dan pada masa ini fungsi Wait() mungkin sudah dilaksanakan, malah fungsi Wait() dilaksanakan sebelum semua Add() dilaksanakan Apabila Wait() dilaksanakan, ia serta-merta memenuhi pembilang WaitGroup 0, Tunggu tamat dan program utama. keluar, menyebabkan semua sub-coroutine Sebelum ia keluar sepenuhnya, fungsi utama tamat.

Pendekatan yang betul

Fungsi Tambah mesti dilaksanakan sebelum fungsi Tunggu dilaksanakan Ini dicadangkan dalam dokumentasi fungsi Tambah: Perhatikan bahawa panggilan dengan delta positif yang berlaku apabila pembilang adalah sifar mesti berlaku sebelum Tunggu..

Bagaimana untuk memastikan bahawa fungsi Tambah mesti dilaksanakan sebelum fungsi Tunggu? Dalam kes coroutine, kami tidak boleh meramalkan sama ada masa pelaksanaan kod dalam coroutine lebih awal daripada masa pelaksanaan fungsi Tunggu Walau bagaimanapun, kami boleh memastikan bahawa dengan melaksanakan fungsi Tambah sebelum menetapkan coroutine dan kemudian melaksanakan Tunggu. fungsi.

Berikut ialah program yang diubah suai dan hasil output.

package main

import (
    "fmt"
    "sync"
)

func father(wg *sync.WaitGroup) {
    defer wg.Done()

    fmt.Printf("father\n")
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go child(wg, i)
    }
}

func child(wg *sync.WaitGroup, id int) {
    defer wg.Done()
    fmt.Printf("child [%d]\n", id)
}

func main() {
    var wg sync.WaitGroup
    wg.Add(1)
    go father(&wg)

    wg.Wait()
    fmt.Println("main: father and all chindren exit")
}
father
child [9]
child [7]
child [8]
child [1]
child [4]
child [5]
child [2]
child [6]
child [0]
child [3]
main: father and all chindren exit

Atas ialah kandungan terperinci Analisis perangkap WaitGroup Golang dan selesaikan masalah. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:segmentfault.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam