Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Jalan buntu - semua gorouti sedang tidur (walaupun menggunakan kumpulan menunggu)

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

PHPz
PHPzke hadapan
2024-02-09 13:40:081112semak imbas

死锁 - 所有 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()

}

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()

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
    }
}

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
....

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!

Kenyataan:
Artikel ini dikembalikan pada:stackoverflow.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam