Jalan buntu - semua gorouti sedang tidur (walaupun menggunakan kumpulan menunggu)

PHPz
Lepaskan: 2024-02-09 13:40:08
ke hadapan
1112 orang telah melayarinya

死锁 - 所有 goroutine 都处于睡眠状态(即使使用等待组)

Editor PHP Xiaoxin berada di sini untuk memperkenalkan kepada anda masalah pengaturcaraan serentak yang biasa-kebuntuan. Kebuntuan bermakna semua goroutine telah memasuki keadaan tidur dan tidak boleh terus melaksanakan walaupun mekanisme seperti kumpulan menunggu digunakan. Dalam kes ini, semua gorout tidak dapat bergerak ke hadapan, menyebabkan program jatuh ke dalam keadaan menunggu yang tidak terhingga. Dalam pengaturcaraan serentak, adalah sangat penting untuk mengelakkan kebuntuan, dan kita perlu memahami punca dan penyelesaiannya untuk memastikan operasi normal program.

Kandungan soalan

Saya sedang belajar go concurrency dan saya mahukan rutin two go untuk terus berkomunikasi antara satu sama lain sambil menyampaikan nilai yang dikemas kini melalui saluran. Satu tambah 2 dan satu lagi tolak 1. Kod dan output adalah seperti berikut:

Apa yang salah dengan kod ini?

package main

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

var wg sync.waitgroup

func addtwo(r chan int, e chan int) {
    val := <-r
    fmt.println("at recieved: ", val)
    time.sleep(1 * time.second)
    e <- val + 2
}

func subtractone(r chan int, e chan int) {
    val := <-r
    fmt.println("so recieved: ", val)
    time.sleep(1 * time.second)
    e <- val - 1
}

func main() {
    ch := make(chan int)
    ch2 := make(chan int)

    wg.add(1)
    go addtwo(ch, ch2)

    wg.add(1)
    go subtractone(ch2, ch)

    ch <- 1
    wg.wait()

}
Salin selepas log masuk

Keluaran:

AT Recieved:  1
SO Recieved:  3
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [semacquire]:
sync.runtime_Semacquire(0x4b2de8?)
    /usr/lib/go-1.18/src/runtime/sema.go:56 +0x25
sync.(*WaitGroup).Wait(0x0?)
    /usr/lib/go-1.18/src/sync/waitgroup.go:136 +0x52
main.main()
Salin selepas log masuk

Kemudian ia berhenti.

Mengapa goroutine tidak sentiasa menukar nilai walaupun saya tidak memanggil wg.done() dalam goroutine?

Penyelesaian

Kedua-dua gorout yang anda mulakan hanya menerima nilai dan menghantar nilai dan kemudian tamat. Dari sana, ia hanya main goroutine,在 wg.wait() 处被阻止,因为你从未调用 wg.done().

Anda terlupa menggunakan gelung (n infinite):

func addtwo(r chan int, e chan int) {
    for {
        val := <-r
        fmt.println("at recieved: ", val)
        time.sleep(1 * time.second)
        e <- val + 2
    }
}

func subtractone(r chan int, e chan int) {
    for {
        val := <-r
        fmt.println("so recieved: ", val)
        time.sleep(1 * time.second)
        e <- val - 1
    }
}
Salin selepas log masuk

Dengan perubahan ini aplikasi anda akan berjalan selama-lamanya dan outputnya ialah:

AT Recieved:  1
SO Recieved:  3
AT Recieved:  2
SO Recieved:  4
AT Recieved:  3
SO Recieved:  5
AT Recieved:  4
....
Salin selepas log masuk

Atas ialah kandungan terperinci Jalan buntu - semua gorouti sedang tidur (walaupun menggunakan kumpulan menunggu). Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:stackoverflow.com
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
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan
Tentang kita Penafian Sitemap
Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!