Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Cara untuk membetulkan isu ini: Panik: Penyegerakan: Kaunter WaitGroup Negatif

Cara untuk membetulkan isu ini: Panik: Penyegerakan: Kaunter WaitGroup Negatif

PHPz
PHPzke hadapan
2024-02-05 21:42:091182semak imbas

如何解决此问题:恐慌:同步:负数 WaitGroup 计数器

Kandungan soalan

Saya kadang-kadang menghadapi masalah ini selepas menjalankannya berulang kali. Saya tahu ini berkaitan dengan kaunter. Ia membuang ralat ini apabila kaedah done() sync.waitgroup dipanggil lebih banyak kali daripada kaedah add() dipanggil.

Bagaimana untuk menyelesaikan masalah ini?

Kod saya mencipta kelompok bersaiz 4 dan melakukan beberapa pemprosesan pada setiap kelompok, tetapi saya menghadapi masalah untuk menyelesaikan panik ini.

package main

import (
    "fmt"
    "sync"
)

func main() {
    // create input channel
    input := make(chan int)

    // create wait group
    var wg sync.waitgroup

    // start batcher goroutine
    wg.add(1)
    go batcher(input, &wg)

    // send input values to the batcher
    for i := 1; i <= 10; i++ {
        input <- i
    }

    // close input channel
    close(input)

    // wait for batcher goroutine to finish
    wg.wait()
}

func batcher(input chan int, wg *sync.waitgroup) {
    // create batch channel with buffer of size 4
    batch := make(chan int, 4)

    // create channel to synchronize worker goroutines
    done := make(chan bool)

    // create wait group for worker goroutines
    var workerwg sync.waitgroup

    // start worker goroutines
    for i := 0; i < 4; i++ {
        workerwg.add(1)
        go worker(batch, &workerwg, done)
    }

    // read input values and send to batch
    for value := range input {
        batch <- value
        if len(batch) == 4 {
            // wait for worker goroutines to finish processing batch
            workerwg.wait()

            // send batch to worker goroutines
            for i := 0; i < 4; i++ {
                workerwg.add(1)
                go sendbatch(batch, &workerwg, done)
            }
        }
    }

    // wait for worker goroutines to finish processing remaining batch
    workerwg.wait()

    // close done channel to notify that all batches have been processed
    close(done)

    wg.done()
}

func sendbatch(batch chan int, workerwg *sync.waitgroup, done chan bool) {
    // process batch
    for value := range batch {
        fmt.println("processing value:", value)
    }

    // notify worker goroutines that batch has been processed
    workerwg.done()

    select {
    case done <- true:
    default:
        // done channel has been closed
    }
}

func worker(batch chan int, workerwg *sync.waitgroup, done chan bool) {
    // process batches received from batch channel
    for batch := range batch {
        // process batch
        fmt.println("processing batch:", batch)
        workerwg.done()
    }

    // notify batcher goroutine that worker goroutine has finished
    select {
    case done <- true:
    default:
        // done channel has been closed
    }
}

Kod asas untuk menulis program kelompok:

package main

import (
    "fmt"
    "sync"
)

func main() {
    input := make(chan int)
    output := make(chan []int)

    var wg sync.waitgroup
    wg.add(2)

    // start the batcher goroutine
    go func() {
        batch := []int{}
        for value := range input {
            batch = append(batch, value)
            if len(batch) == 4 {
                output <- batch
                batch = []int{}
            }
        }
        if len(batch) > 0 {
            output <- batch
        }
        close(output)
        wg.done()
    }()

    // start the worker goroutine
    go func() {
        for batch := range output {
            sum := 0
            for _, value := range batch {
                sum += value
            }
            fmt.printf("sum of batch %v: %d\n", batch, sum)
        }
        wg.done()
    }()

    // send input values to the batcher
    for _, v := range []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} {
        input <- v
    }
    close(input)

    // wait for both goroutines to finish
    wg.wait()
}
Sum of batch [1 2 3 4]: 10
Sum of batch [5 6 7 8]: 26
Sum of batch [9 10]: 19

Reka bentuk awal agak kompleks, saya akan cuba kembangkan pada reka bentuk asas ini.


Jawapan betul


Mengikut kod ini:

for i := 0; i < 4; i++ {
    workerwg.add(1)
    go worker(batch, &workerwg, done)
}

Saya rasa workerwg.done() harus dialihkan ke luar gelung:

func worker(batch chan int, workerWg *sync.WaitGroup, done chan bool) {
+   defer workerWg.Done()
    // process batches received from batch channel
    for batch := range batch {
        // process batch
        fmt.Println("Processing batch:", batch)
-       workerWg.Done()
    }

    // notify batcher goroutine that worker goroutine has finished
    select {
    case done <- true:
    default:
        // done channel has been closed
    }
  }

Tetapi batch tidak ditutup dalam demo. Jadi sebenarnya, goroutine akan berjalan selama-lamanya sehingga program tamat.

Tidak pasti jika terdapat sebarang soalan lain. Reka bentuknya terlalu kompleks. Kod kompleks sukar difahami dan terdedah kepada ralat. Pertimbangkan untuk mereka bentuk semula.

Atas ialah kandungan terperinci Cara untuk membetulkan isu ini: Panik: Penyegerakan: Kaunter WaitGroup Negatif. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

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