Jadual Kandungan
Kandungan soalan
Penyelesaian
Cara yang lebih baik: gunakan nilsaluran yang boleh untuk pemilihan
Rumah pembangunan bahagian belakang Golang Apakah amalan terbaik di Golang untuk menjejak status penyiapan dua Goroutine dalam Goroutine ketiga?

Apakah amalan terbaik di Golang untuk menjejak status penyiapan dua Goroutine dalam Goroutine ketiga?

Feb 11, 2024 pm 02:54 PM
overflow

Golang 中跟踪第三个 Goroutine 中两个 Goroutine 的完成状态的最佳实践是什么?

Apakah amalan terbaik di Golang untuk menjejak status penyiapan dua Goroutine dalam Goroutine ketiga? Di Golang, untuk menjejak status penyiapan dua Goroutine dan memproses keputusan mereka dalam Goroutine ketiga, amalan terbaik ialah menggunakan WaitGroup daripada pakej penyegerakan. WaitGroup membolehkan kami menunggu di Goroutine utama untuk menyiapkan Goroutine lain. Pertama, kita perlu mencipta objek WaitGroup dan memanggil kaedah Tambah dalam Goroutine utama untuk menetapkan bilangan Goroutine yang menunggu. Kemudian, kaedah Selesai dipanggil pada penghujung setiap Goroutine untuk menandakan siapnya Goroutine tersebut. Akhir sekali, kaedah Tunggu dipanggil dalam Goroutine ketiga untuk menunggu semua Goroutine selesai. Dengan cara ini, kami boleh menjejak dan memproses hasil kedua-dua Goroutine dengan selamat. Ini ialah amalan terbaik di Golang untuk menjejak status penyiapan berbilang Goroutine.

Kandungan soalan

Saya mempunyai tiga gorout berjalan serentak. Dua daripada mereka melakukan beberapa pemprosesan dan menghantar hasil mereka ke saluran hasil. Goroutine ketiga "mengira" keputusan dengan membaca saluran hasil. Saya boleh menggunakan kumpulan tunggu untuk menunggu dua gorout pengiraan selesai dan kemudian melelang ke atas saluran hasil untuk mengira keputusan, tetapi ini tidak berskala dan memerlukan saya membuat saluran hasil penimbal dengan saiz penimbal yang besar, yang tidak boleh diterima dalam kod pengeluaran.

Saya ingin mengira keputusan semasa pemprosesan sedang berlaku, tetapi saya tidak mahu keluar dari program sebelum semua pengiraan selesai. Apakah amalan terbaik untuk mencapai perkara ini dalam Go?

Ini adalah kaedah semasa saya dan ia berfungsi dengan baik. Saya tertanya-tanya sama ada terdapat cara yang lebih baik kerana ini kelihatan agak kikuk?

package main

import (
    "fmt"
    "sync"
)

type T struct{}

func main() {
    var widgetInventory int = 1000
    transactions := make(chan int, 100)
    salesDone := make(chan T)
    purchasesDone := make(chan T)
    var wg sync.WaitGroup
    fmt.Println("Starting inventory count = ", widgetInventory)

    go makeSales(transactions, salesDone)
    go newPurchases(transactions, purchasesDone)

    wg.Add(1)

    go func() {
        salesAreDone := false
        purchasesAreDone := false

        for {
            select {
            case transaction := <-transactions:
                widgetInventory += transaction
            case <-salesDone:
                salesAreDone = true
            case <-purchasesDone:
                purchasesAreDone = true
            default:
                if salesAreDone && purchasesAreDone {
                    wg.Done()
                    return
                }
            }
        }
    }()

    wg.Wait()
    fmt.Println("Ending inventory count = ", widgetInventory)
}

func makeSales(transactions chan int, salesDone chan T) {
    for i := 0; i < 3000; i++ {
        transactions <- -100
    }

    salesDone <- struct{}{}
}

func newPurchases(transactions chan int, purchasesDone chan T) {
    for i := 0; i < 3000; i++ {
        transactions <- 100
    }

    purchasesDone <- struct{}{}
}
Salin selepas log masuk

Penyelesaian

tidak menepati sebarang definisi munasabahbaik. Anda mempunyai gelung for yang popular di sini:

for {
            select {
            case transaction := <-transactions:
                widgetInventory += transaction
            case <-salesDone:
                salesAreDone = true
            case <-purchasesDone:
                purchasesAreDone = true
            default:
                if salesAreDone && purchasesAreDone {
                    wg.Done()
                    return
                }
            }
        }
Salin selepas log masuk

Selagi tiada saluran untuk dibaca, kes default akan dilaksanakan. Ini banyak berlaku kerana cara saluran berfungsi.

Versi kod yang dilaraskan sedikit ini menggambarkan "panas" gelung ini. Hasil yang tepat akan berbeza-beza dan mungkin agak tinggi.

Default case ran 27305 times
Salin selepas log masuk

Anda tidak mahu kes selecting 来自通道时,您不希望出现 default apabila memilihdari saluran, melainkan lalai itu turut menyekat sesuatu di dalamnya. Jika tidak, anda akan mendapat kitaran haba seperti ini.

Cara yang lebih baik: gunakan nilsaluran yang boleh untuk pemilihan

Biasanya dalam pilihan, anda ingin mengenal pasti saluran tertutup dan menetapkan pembolehubah saluran kepada nilselect 永远不会成功地从 nil

; pilih tidak akan berjaya membaca daripada saluran

, jadi ini "melumpuhkan" pilihan dengan berkesan. Pertimbangkan versi ubah suai ini

kod

: salesDonepurchasesDone 都被“发出信号”,我们 close(transactions)。一旦我们耗尽 transactions 并且它被关闭,我们将 transactions 设置为 nil。我们在 transactions 不为 nil 时循环,在这段代码中,意味着所有通道都是 nil

go func(transactions chan int, salesDone <-chan T, purchasesDone <-chan T) {
        defer wg.Done()
        for transactions != nil {
            select {
            case transaction, ok := <-transactions:
                if ok {
                    widgetInventory += transaction
                } else {
                    transactions = nil
                }
            case <-salesDone:
                salesDone = nil
                if purchasesDone == nil {
                    close(transactions)
                }
            case <-purchasesDone:
                purchasesDone = nil
                if salesDone == nil {
                    close(transactions)
                }

            }
        }
    }(transactions, salesDone, purchasesDone)
Salin selepas log masuk

Dengan pelarasan ini kepada pengguna, kami tidak lagi mempunyai gelung panas; kami sentiasa menyekat sehingga data dibaca dari saluran. Setelah kedua-dua salesDone dan purchasesDone telah "diisyaratkan", kami menutup(transaksi). Sebaik sahaja kami kehabisan urus niaga

dan main 共享范围。否则,将 transactions 设置为 nil 将写入一个在 goroutine 之间共享的变量。然而在这种情况下,无论如何,这并不重要,因为我们“知道”我们是最后一个从 transactions ia ditutup, kami menetapkan urus niaga kepada sifar. Kami gelung apabila urus niaga tidak sifar, yang dalam kod ini bermakna semua saluran adalah

.

Perkara halus tetapi penting: Saya menghantar saluran ke fungsi ini supaya rujukannya tidak berkongsi skop dengan utama. Jika tidak, menetapkan transaksi kepada

akan menulis kepada pembolehubah yang dikongsi antara goroutine. Walau bagaimanapun, dalam kes ini, ia tidak penting, kerana kami "tahu" kami adalah orang terakhir yang membaca daripada transaksi. transactions 的生产。然后你想排空 transactions。一旦通道关闭并排空,main

Pilihan yang lebih mudah: berbilang kumpulan menunggu

select 来执行此操作。而 selectJika anda berfikir tentang apa yang anda lakukan di sini, anda perlu menunggu sehingga kedua-dua pengeluar selesai menggandingkan

sebelum anda tahu jumlahnya lengkap.

Anda tidak perlu 🎜 mempunyai kes untuk setiap "pekerja", yang boleh dikatakan agak tidak elegan; anda perlu mengeraskan beberapa pekerja dan mengendalikan saluran "penyelesaian" secara individu. 🎜 🎜Apa yang anda perlu lakukan ialah:🎜
  • 除了为生产者使用一个 var resultswgsync.WaitGroup 之外,还为消费者添加一个。
  • 生产者 defer wg.Done()
  • 消费者 defer resultswg.Done() 在遍历 transactions 之前:
    go func() {
        defer resultswg.Done()
        for transaction := range transactions {
            widgetInventory += transaction
        }
    }()
    Salin selepas log masuk
  • main 处理等待生产者、关闭事务以结束范围,然后等待消费者:
    wg.Wait()
    close(transactions)
    resultswg.Wait()
    Salin selepas log masuk

以这种方式编码,最终会变得简短而甜蜜

package main

import (
    "fmt"
    "sync"
)

func main() {
    var widgetInventory int = 1000
    transactions := make(chan int, 100)

    var wg, resultswg sync.WaitGroup
    fmt.Println("Starting inventory count = ", widgetInventory)
    wg.Add(2)

    go makeSales(transactions, &wg)
    go newPurchases(transactions, &wg)
    resultswg.Add(1)
    go func() {
        defer resultswg.Done()
        for transaction := range transactions {
            widgetInventory += transaction
        }
    }()

    wg.Wait()
    close(transactions)
    resultswg.Wait()
    fmt.Println("Ending inventory count = ", widgetInventory)
}

func makeSales(transactions chan int, wg *sync.WaitGroup) {
    defer wg.Done()
    for i := 0; i < 3000; i++ {
        transactions <- -100
    }

}

func newPurchases(transactions chan int, wg *sync.WaitGroup) {
    defer wg.Done()
    for i := 0; i < 3000; i++ {
        transactions <- 100
    }

}
Salin selepas log masuk

您可以在这里看到,在此模式中可以有任意数量的生产者;您只需为每个生产者添加 wg.Add(1) 即可。

当我不知道每个工作人员会返回多少结果时,我一直使用这种模式来并行化工作。我发现它很容易理解,并且比尝试 select 多个通道简单得多。事实上,我什至想说,如果您发现自己从多个渠道进行 selecting,您应该退后一步,确保它对您来说确实有意义。我使用 select 的频率远远低于使用等待组的频率。

Atas ialah kandungan terperinci Apakah amalan terbaik di Golang untuk menjejak status penyiapan dua Goroutine dalam Goroutine ketiga?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan Laman Web ini
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

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

AI Hentai Generator

AI Hentai Generator

Menjana ai hentai secara percuma.

Artikel Panas

R.E.P.O. Kristal tenaga dijelaskan dan apa yang mereka lakukan (kristal kuning)
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Tetapan grafik terbaik
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Cara Memperbaiki Audio Jika anda tidak dapat mendengar sesiapa
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌

Alat panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1

Hantar Studio 13.0.1

Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Harga Bitcoin sejak kelahirannya 2009-2025 Ringkasan paling lengkap harga sejarah BTC Harga Bitcoin sejak kelahirannya 2009-2025 Ringkasan paling lengkap harga sejarah BTC Jan 15, 2025 pm 08:11 PM

Sejak penubuhannya pada tahun 2009, Bitcoin telah menjadi peneraju dalam dunia mata wang kripto dan harganya telah mengalami turun naik yang besar. Untuk memberikan gambaran keseluruhan sejarah yang komprehensif, artikel ini menyusun data harga Bitcoin dari 2009 hingga 2025, meliputi peristiwa pasaran utama, perubahan dalam sentimen pasaran dan faktor penting yang mempengaruhi pergerakan harga.

Gambaran keseluruhan harga sejarah Bitcoin sejak kelahirannya Koleksi lengkap trend harga sejarah Bitcoin. Gambaran keseluruhan harga sejarah Bitcoin sejak kelahirannya Koleksi lengkap trend harga sejarah Bitcoin. Jan 15, 2025 pm 08:14 PM

Bitcoin, sebagai mata wang kripto, telah mengalami turun naik pasaran yang ketara sejak penubuhannya. Artikel ini akan memberikan gambaran keseluruhan harga sejarah Bitcoin sejak kelahirannya untuk membantu pembaca memahami arah aliran harga dan detik pentingnya. Dengan menganalisis data harga sejarah Bitcoin, kami dapat memahami penilaian pasaran terhadap nilainya, faktor yang mempengaruhi turun naiknya, dan menyediakan asas untuk keputusan pelaburan masa hadapan.

Senarai harga sejarah sejak kelahiran carta Trend Harga Sejarah Bitcoin BTC (Ringkasan Terkini) Senarai harga sejarah sejak kelahiran carta Trend Harga Sejarah Bitcoin BTC (Ringkasan Terkini) Feb 11, 2025 pm 11:36 PM

Sejak penciptaannya pada tahun 2009, harga Bitcoin telah mengalami beberapa turun naik utama, meningkat kepada $ 69,044.77 pada November 2021 dan jatuh ke $ 3,191.22 pada Disember 2018. Sehingga Disember 2024, harga terkini telah melebihi $ 100,204.

Harga terbaru Bitcoin pada 2018-2024 USD Harga terbaru Bitcoin pada 2018-2024 USD Feb 15, 2025 pm 07:12 PM

Harga USD Bitcoin masa nyata Faktor yang menjejaskan harga bitcoin Petunjuk untuk meramalkan harga bitcoin masa depan Berikut adalah beberapa maklumat penting mengenai harga Bitcoin pada 2018-2024:

Ringkasan Butiran Harga Sejarah yang Paling Lengkap Sejak Kelahiran Bitcoin (versi terkini pada tahun 2025) Ringkasan Butiran Harga Sejarah yang Paling Lengkap Sejak Kelahiran Bitcoin (versi terkini pada tahun 2025) Feb 15, 2025 pm 06:45 PM

Node penting untuk harga bersejarah Bitcoin 3 Januari 2009: Blok Kejadian dihasilkan, bitcoin pertama dihasilkan, dengan nilai USD 0. 5 Oktober: Transaksi Bitcoin pertama, seorang pengaturcara membeli dua pizza dengan 10,000 bitcoin, bersamaan dengan $ 0.008. 9 Februari 2010: Mt. Gox Exchange pergi dalam talian dan menjadi platform utama untuk perdagangan Bitcoin awal. 22 Mei: Bitcoin memecahkan $ 1 untuk kali pertama. 17 Julai: Harga Bitcoin menjunam ke $ 0.008, memukul rendah sepanjang masa. 9 Februari 2011: Harga bitcoin pecah melalui $ 10 untuk kali pertama. 10 April: Mt. Pergi

Di era CHATGPT, bagaimanakah masyarakat Q & A teknikal dapat bertindak balas terhadap cabaran? Di era CHATGPT, bagaimanakah masyarakat Q & A teknikal dapat bertindak balas terhadap cabaran? Apr 01, 2025 pm 11:51 PM

Komuniti Q & A Teknikal di Era CHATGPT: Strategi Respons Segmentfault StackOverflow ...

Dalam satu artikel, pelajari: Apakah kadar dana mata wang maya dan cara menggunakan kadar dana untuk perdagangan Dalam satu artikel, pelajari: Apakah kadar dana mata wang maya dan cara menggunakan kadar dana untuk perdagangan Feb 15, 2025 pm 10:06 PM

Kadar pendanaan mata wang maya adalah yuran yang dikenakan kepada peniaga yang memegang jawatan dalam perdagangan derivatif. Ia mencerminkan premium atau diskaun antara harga pasaran tempat dan harga kontrak niaga hadapan apabila kontrak tamat. Apabila harga spot lebih tinggi daripada harga niaga hadapan, kadar modal adalah negatif, yang bermaksud bahawa peniaga -peniaga yang berpendapatan pendek membayar yuran kepada pedagang yang jangka panjang. Sebaliknya, apabila harga spot lebih rendah daripada harga niaga hadapan, kadar modal adalah positif, yang bermaksud bahawa peniaga yang melakukan yuran membayar panjang kepada peniaga yang melakukan kedudukan pendek.

Bagaimana cara menggunakan atribut clip-path CSS untuk mencapai kesan lengkung 45 darjah segmen? Bagaimana cara menggunakan atribut clip-path CSS untuk mencapai kesan lengkung 45 darjah segmen? Apr 04, 2025 pm 11:45 PM

Bagaimana untuk mencapai kesan lengkung 45 darjah segmen? Dalam proses melaksanakan segmen, bagaimana membuat sempadan yang betul berubah menjadi lengkung 45 darjah ketika mengklik butang kiri, dan titik ...

See all articles