Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Bagaimana untuk menutup saluran yang diisi oleh berbilang goroutine apabila semua kerja selesai?

Bagaimana untuk menutup saluran yang diisi oleh berbilang goroutine apabila semua kerja selesai?

WBOY
WBOYke hadapan
2024-02-10 12:27:10792semak imbas

当所有工作完成后,如何关闭由多个 goroutine 填充的通道?

Cara menutup saluran yang diisi oleh berbilang goroutine apabila semua kerja selesai adalah soalan yang sering ditanya. Dalam Go, menutup saluran ialah cara untuk memberitahu penerima bahawa tiada lagi data. Dengan menutup saluran, penerima boleh mengetahui tepat pada masanya bahawa pengirim telah menyelesaikan semua operasi penghantaran. Dalam saluran yang dipenuhi dengan berbilang goroutin, kita boleh menggunakan kaunter untuk menjejaki berapa banyak lagi goroutin yang menghantar data ke saluran. Apabila kaunter turun kepada 0, semua kerja telah selesai dan kami boleh menutup saluran dengan selamat. Selepas menutup saluran, penerima boleh menentukan sama ada saluran telah ditutup dengan menggunakan pembolehubah tambahan dalam ungkapan terima. Dengan cara ini, kami boleh memastikan saluran yang diisi oleh berbilang goroutin ditutup dengan betul selepas semua kerja selesai, sekali gus mengelakkan kebocoran sumber dan isu kebuntuan.

Kandungan soalan

Saya cuba mengikuti cara Go iaitu "jangan berkomunikasi melalui memori yang dikongsi, tetapi berkongsi memori melalui komunikasi" dan menggunakan saluran untuk menyampaikan tugasan secara tidak segerak untuk diselesaikan dan menghantar semula hasil tugasan pemprosesan.

Untuk memudahkan, saya telah menukar jenis saluran kepada int dan bukannya struktur sebenar mereka. Dan menggantikan pemprosesan lama dengan time.Sleep().

Bagaimana untuk menutup ProducedResults ,以便此代码不会卡在最后一个 for selepas semua keputusan tugasan dihantar semula?

quantityOfTasks:= 100
    quantityOfWorkers:= 60
    remainingTasks := make(chan int)
    producedResults := make(chan int)

    // produce tasks
    go func() {
        for i := 0; i < quantityOfTasks; i++ {
            remainingTasks <- 1
        }
        close(remainingTasks)
    }()

    // produce workers
    for i := 0; i < quantityOfWorkers; i++ {
        go func() {
            for taskSize := range remainingTasks {
                // simulate a long task
                time.Sleep(time.Second * time.Duration(taskSize))
                // return the result of the long task
                producedResults <- taskSize
            }
        }()
    }

    // read the results of the tasks and agregate them
    executedTasks := 0
    for resultOfTheTask := range producedResults { //this loop will never finish because producedResults never gets closed
        // consolidate the results of the tasks
        executedTasks += resultOfTheTask
    }

Penyelesaian

Anda mahu menutup saluran selepas semua goroutine yang menulis kepadanya telah kembali. Anda boleh menggunakan WaitGroup untuk mencapai:

wg:=sync.WaitGroup{}

for i := 0; i < quantityOfWorkers; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            for taskSize := range remainingTasks {
                //simulate a long task
                time.Sleep(time.Second * time.Duration(taskSize))
                //return the result of the long task
                producedResults <- taskSize
            }
        }()
}

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

Atas ialah kandungan terperinci Bagaimana untuk menutup saluran yang diisi oleh berbilang goroutine apabila semua kerja selesai?. 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