Jadual Kandungan
Kandungan soalan
解决方法
Rumah pembangunan bahagian belakang Golang Mengapakah kebuntuan berlaku apabila panggilan fungsi yang mengisi saluran tidak dibenamkan dalam Goroutine?

Mengapakah kebuntuan berlaku apabila panggilan fungsi yang mengisi saluran tidak dibenamkan dalam Goroutine?

Feb 10, 2024 pm 12:00 PM

当填充通道的函数调用未嵌入 Goroutine 中时,为什么会出现死锁?

Apabila panggilan fungsi yang mengisi saluran tidak dibenamkan dalam Goroutine, sebab kebuntuan berlaku adalah kerana operasi hantar dan terima saluran disekat. Jika fungsi yang mengisi saluran dipanggil dalam Goroutine utama, dan operasi pengisian tidak dimasukkan ke dalam Goroutine baharu untuk dijalankan di dalam fungsi, maka Goroutine utama akan menunggu saluran mempunyai ruang yang cukup untuk menerima data, dan operasi mengisi tidak dapat dilakukan, dengan itu Membawa kepada kebuntuan. Oleh itu, untuk mengelakkan kebuntuan, kita perlu menggunakan Goroutine untuk pelaksanaan serentak dalam operasi mengisi saluran bagi memastikan operasi pengisian dan operasi penerimaan dapat dilakukan pada masa yang sama.

Kandungan soalan

Saya tahu tentang pilihan sync 包及其 waitgroup dan saya tidak mahu menggunakannya untuk ujian ini. Saya sedang menguji semafor.

Jadi saya ada:

package main

import (
    "fmt"
    "os"
    "time"
)

func main() {

    fmt.print("wassap")

    jobs := make(chan int)
    processstarted := make(chan struct{}, 1)
    processcompleted := make(chan struct{}, 1)

    createjobs(jobs)

    go func() {
        worker(jobs, processstarted, processcompleted)
    }()

    go func() {
        sync(processstarted, processcompleted)
    }()

    time.sleep(3600 * time.second)
    fmt.print("\nend of main...")

    interrupt := make(chan os.signal)
    <-interrupt

}

func createjobs(jobs chan<- int) {
    defer close(jobs)
    for i := 1; i < 20; i++ {
        jobs <- i
    }
}

func worker(jobs <-chan int, processstarted <-chan struct{}, processcompleted <-chan struct{}) {

    for {
        select {
        case i := <-jobs:
            fmt.printf("\nfetching job #%d from channel", i)
            time.sleep(2 * time.second)
        case <-processstarted:
            fmt.print("\nprocess started. waiting for it to be completed")
            <-processcompleted
            fmt.print("\nprocess completed")
        }

    }
}

func sync(processstarted chan<- struct{}, processcompleted chan<- struct{}) {

    // acquire semaphore. send signal to channel to indicate that it is busy
    processstarted <- struct{}{}

    for i := 1; i < 5; i++ {
        fmt.printf("\nprocessing %d", i)
        time.sleep(5 * time.second)
    }

    // release semaphore
    processcompleted <- struct{}{}
}
Salin selepas log masuk

Apa yang saya ingin uji adalah sangat mudah: Saya mempunyai createjobs 函数,其唯一目的是将元素添加到通道,在本例中是一个 int 通道。然后我有一个 worker yang akan mengekstrak objek dari saluran itu dan tidur selama 2 saat sebelum mengekstrak elemen seterusnya.

Kini, terdapat juga fungsi penyegerakan. Satu-satunya tujuan fungsi ini adalah untuk mensimulasikan elemen worker 运行时启动的进程。如果此进程处于活动状态,则在 sync 结束时应停止处理 jobs, itulah sebabnya saya mempunyai dua saluran, satu menunjukkan bahawa proses telah dimulakan dan satu lagi bahawa proses telah tamat.

Saya mendapat ralat berikut semasa menjalankan kod saya:

fatal error: all goroutines are asleep - deadlock!
Salin selepas log masuk

Jika saya mengubah suai cara createjobs dipanggil, bungkusnya dalam goroutine seperti ini:

go func() {
        createJobs(jobs)
    }()
Salin selepas log masuk

Kemudian kod saya berjalan dengan betul.

Saya cuma nak faham kenapa ini berlaku. Apa yang saya maksudkan ialah: rutin main sedang dilaksanakan dan kemudian ia memanggil main 例程正在执行,然后它调用 createjobs (无换行),因此 main 例程应该被阻止,直到此调用结束。一旦 createjobs 结束,就说明通道中有元素了。 main 继续执行并启动其他 goroutine workersync 来完成它们的工作。在 main (tanpa baris baharu), jadi rutin main harus disekat sehingga panggilan ini tamat. Sebaik sahaja

tamat, bermakna ada elemen dalam saluran. utama meneruskan pelaksanaan dan memulakan gorout lain pekerja dan sync untuk menyelesaikan kerja mereka. Sebelum utama tamat, saya hanya menambah sleeper untuk memberi masa goroutine yang dibuat sebelum ini untuk disiapkan.

createjobs 发生在 goroutine 之外时会发生什么。

解决方法

您将 jobs 声明为无缓冲通道,然后尝试将 20 个值同步推入其中。当您调用 createjobs(jobs)Saya tidak meminta penyelesaian lain untuk masalah ini, saya cuma ingin tahu apa yang berlaku apabila

berlaku di luar goroutine.

Penyelesaian

Anda mengisytiharkan pekerjaan sebagai saluran yang tidak ditimbal dan kemudian cuba menolak 20 nilai ke dalamnya secara serentak. Ini akan menyekat fungsi utama anda apabila anda memanggil

. Tukar baris 13 kepada:

    jobs := make(chan int, 20)
Salin selepas log masuk

...akan menyelesaikan kebuntuan.

EDIT - Penjelasan diminta dalam ulasan:

createjobs(jobs)

Saluran tidak buffer tidak mempunyai kapasiti dan menyekat pelaksanaan pengeluar sehingga pengguna menerima mesej.

Satu analogi yang baik untuk saluran yang tidak dibuffer ialah paip, dalam kes ini prosesnya kelihatan seperti ini:

+------------------+     +------------+      +-------------+
| PRODUCER         |     | PIPE       |      | CONSUMER    |
|                  +---->|            +----->|             |
| createJobs(jobs) |     | unbuffered |      | worker(...) |
|                  |     | channel    |      |             |
+------------------+     +------------+      +-------------+
Salin selepas log masuk
Kebuntuan berlaku kerana

dipanggil serentak dan belum ada pengguna yang sedang berjalan. main()

Ia berfungsi apabila memanggil fungsi (🎜pengeluar🎜) dalam goroutine kerana pada asasnya memasukkan saluran dan membaca saluran berlaku secara selari? 🎜 🎜Ya. Jika pengeluar dipanggil secara tidak segerak, ia tidak akan menyekat fungsi 🎜, jadi pengguna juga berpeluang untuk dipanggil. Dalam kes ini, pengeluar akan menolak semua tugasnya satu demi satu, sama seperti pekerja memakannya satu demi satu. 🎜

Atas ialah kandungan terperinci Mengapakah kebuntuan berlaku apabila panggilan fungsi yang mengisi saluran tidak dibenamkan dalam Goroutine?. 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

Video Face Swap

Video Face Swap

Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

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)

Apakah kelemahan debian openssl Apakah kelemahan debian openssl Apr 02, 2025 am 07:30 AM

OpenSSL, sebagai perpustakaan sumber terbuka yang digunakan secara meluas dalam komunikasi yang selamat, menyediakan algoritma penyulitan, kunci dan fungsi pengurusan sijil. Walau bagaimanapun, terdapat beberapa kelemahan keselamatan yang diketahui dalam versi sejarahnya, yang sebahagiannya sangat berbahaya. Artikel ini akan memberi tumpuan kepada kelemahan umum dan langkah -langkah tindak balas untuk OpenSSL dalam sistem Debian. Debianopenssl yang dikenal pasti: OpenSSL telah mengalami beberapa kelemahan yang serius, seperti: Kerentanan Pendarahan Jantung (CVE-2014-0160): Kelemahan ini mempengaruhi OpenSSL 1.0.1 hingga 1.0.1f dan 1.0.2 hingga 1.0.2 versi beta. Penyerang boleh menggunakan kelemahan ini untuk maklumat sensitif baca yang tidak dibenarkan di pelayan, termasuk kunci penyulitan, dll.

Perpustakaan apa yang digunakan untuk operasi nombor terapung di GO? Perpustakaan apa yang digunakan untuk operasi nombor terapung di GO? Apr 02, 2025 pm 02:06 PM

Perpustakaan yang digunakan untuk operasi nombor terapung dalam bahasa Go memperkenalkan cara memastikan ketepatannya ...

Apakah masalah dengan thread giliran di crawler colly go? Apakah masalah dengan thread giliran di crawler colly go? Apr 02, 2025 pm 02:09 PM

Masalah Threading Giliran di GO Crawler Colly meneroka masalah menggunakan Perpustakaan Colly Crawler dalam bahasa Go, pemaju sering menghadapi masalah dengan benang dan permintaan beratur. � ...

Berubah dari front-end ke pembangunan back-end, adakah lebih menjanjikan untuk belajar Java atau Golang? Berubah dari front-end ke pembangunan back-end, adakah lebih menjanjikan untuk belajar Java atau Golang? Apr 02, 2025 am 09:12 AM

Laluan Pembelajaran Backend: Perjalanan Eksplorasi dari Front-End ke Back-End sebagai pemula back-end yang berubah dari pembangunan front-end, anda sudah mempunyai asas Nodejs, ...

Di Go, mengapa rentetan percetakan dengan fungsi println dan rentetan () mempunyai kesan yang berbeza? Di Go, mengapa rentetan percetakan dengan fungsi println dan rentetan () mempunyai kesan yang berbeza? Apr 02, 2025 pm 02:03 PM

Perbezaan antara percetakan rentetan dalam bahasa Go: perbezaan kesan menggunakan fungsi println dan rentetan () sedang ...

Bagaimana cara menentukan pangkalan data yang berkaitan dengan model dalam beego orm? Bagaimana cara menentukan pangkalan data yang berkaitan dengan model dalam beego orm? Apr 02, 2025 pm 03:54 PM

Di bawah rangka kerja beegoorm, bagaimana untuk menentukan pangkalan data yang berkaitan dengan model? Banyak projek beego memerlukan pelbagai pangkalan data untuk dikendalikan secara serentak. Semasa menggunakan beego ...

Bagaimana menyelesaikan masalah penukaran jenis user_id semasa menggunakan aliran redis untuk melaksanakan beratur mesej dalam bahasa Go? Bagaimana menyelesaikan masalah penukaran jenis user_id semasa menggunakan aliran redis untuk melaksanakan beratur mesej dalam bahasa Go? Apr 02, 2025 pm 04:54 PM

Masalah menggunakan redisstream untuk melaksanakan beratur mesej dalam bahasa Go menggunakan bahasa Go dan redis ...

Kaedah Pemantauan PostgreSQL di bawah Debian Kaedah Pemantauan PostgreSQL di bawah Debian Apr 02, 2025 am 07:27 AM

Artikel ini memperkenalkan pelbagai kaedah dan alat untuk memantau pangkalan data PostgreSQL di bawah sistem Debian, membantu anda memahami pemantauan prestasi pangkalan data sepenuhnya. 1. Gunakan PostgreSQL untuk membina pemantauan PostgreSQL sendiri menyediakan pelbagai pandangan untuk pemantauan aktiviti pangkalan data: PG_STAT_ACTIVITY: Memaparkan aktiviti pangkalan data dalam masa nyata, termasuk sambungan, pertanyaan, urus niaga dan maklumat lain. PG_STAT_REPLITI: Memantau status replikasi, terutamanya sesuai untuk kluster replikasi aliran. PG_STAT_DATABASE: Menyediakan statistik pangkalan data, seperti saiz pangkalan data, masa komitmen/masa rollback transaksi dan petunjuk utama lain. 2. Gunakan alat analisis log pgbadg

See all articles