Rumah >pembangunan bahagian belakang >Golang >Bagaimana untuk Menyelesaikan Kebuntuan Pergi yang Disebabkan oleh Operasi Asynchronous dan Saluran Kosong?

Bagaimana untuk Menyelesaikan Kebuntuan Pergi yang Disebabkan oleh Operasi Asynchronous dan Saluran Kosong?

Barbara Streisand
Barbara Streisandasal
2024-12-11 18:04:12244semak imbas

How to Resolve Go Deadlocks Caused by Asynchronous Operations and Empty Channels?

Kebuntuan dalam Go: "semua rutin pergi sedang tidur"

Apabila menjalankan kod yang disediakan, jalan buntu berlaku disebabkan model pelaksanaan tak segeraknya menggunakan goroutine. Isu timbul apabila fungsi UnloadTrucks dipanggil sebelum sebarang trak dihantar ke saluran. Ini membawa kepada saluran kekal kosong, menyebabkan gorout penghantar disekat pada baris ch <- tr. Memandangkan goroutine penghantar sedang menunggu untuk menghantar trak, mereka tidak boleh menutup saluran, dan fungsi UnloadTrucks, yang menunggu untuk menerima trak, tersekat selama-lamanya.

Penyelesaian: Menggunakan WaitGroup untuk Menutup Saluran

Untuk menyelesaikan kebuntuan, kami boleh menutup saluran ch selepas semua goroutine selesai menghantar trak. Ini boleh dicapai dengan memperkenalkan WaitGroup, primitif penyegerakan yang menjejaki bilangan goroutin yang belum selesai:

go func() {
    wg.Wait()
    close(ch)
}()

Groutine ini menunggu sehingga semua goroutine lain menyelesaikan tugas mereka (diisyaratkan oleh panggilan Tunggu() sebelum menutup saluran. Dengan berbuat demikian, fungsi UnloadTrucks dapat keluar dengan anggun apabila semua trak telah dihantar.

Kod Semakan:

package main

import (
    "fmt"
    "sync"
    "time"
)

type Item struct {
    name string
}

type Truck struct {
    Cargo []Item
    name  string
}

func UnloadTrucks(c chan Truck) {

    for t := range c {
        fmt.Printf("%s has %d items in cargo: %s\n", t.name, len(t.Cargo), t.Cargo[0].name)
    }

}

func main() {
    trucks := make([]Truck, 2)

    ch := make(chan Truck)

    var wg sync.WaitGroup
    for i, _ := range trucks {

        trucks[i].name = fmt.Sprintf("Truck %d", i+1)

        fmt.Printf("Building %s\n", trucks[i].name)
    }

    for t := range trucks {
        go func(tr Truck) {

            itm := Item{}
            itm.name = "Groceries"

            fmt.Printf("Loading %s\n", tr.name)
            tr.Cargo = append(tr.Cargo, itm)
            ch <- tr
            wg.Done()

        }(trucks[t])
        wg.Add(1)
    }

    time.Sleep(50 * time.Millisecond)
    fmt.Println("Unloading Trucks")
    UnloadTrucks(ch)

    fmt.Println("Done")
}

Dengan kod yang diubah suai ini, kebuntuan dihapuskan kerana fungsi UnloadTrucks dijamin menerima semua trak sebelum saluran ditutup. Ini memastikan semua gorout menyelesaikan tugas mereka dengan betul dan program berjalan tanpa sebarang gangguan yang tidak dijangka.

Atas ialah kandungan terperinci Bagaimana untuk Menyelesaikan Kebuntuan Pergi yang Disebabkan oleh Operasi Asynchronous dan Saluran Kosong?. 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