Rumah > pembangunan bahagian belakang > Golang > Hentikan goroutine yang menulis ke saluran selama-lamanya

Hentikan goroutine yang menulis ke saluran selama-lamanya

WBOY
Lepaskan: 2024-02-05 23:09:07
ke hadapan
942 orang telah melayarinya

停止无限期写入通道的 goroutine

Kandungan soalan

Saya mempunyai fungsi yang mencipta goroutine yang mengisi saluran selama-lamanya, contohnya:

func foo() <-chan int {
  ch := make(chan int) 
  go func() {
    defer close(ch)
    for {
      ch <- 1
    } 
  }() 
  return ch
}
Salin selepas log masuk

Andaikan kita mempunyai pengguna yang ingin kita hentikan selepas tempoh tertentu:

ch:=foo() 
<-ch
<-ch
// done
Salin selepas log masuk

Sekarang saya mahu membersihkan sumber goroutine, termasuk saluran. Saya cuba menambah saluran "penyelesaian" untuk ini, tetapi kemudian saya menemui jalan buntu:

func Foo() (<-chan int, chan<- bool) {
  ch := make(chan int)
  done := make(chan bool)
  go func() {
    defer close(ch)
    for {
      select {
      case <-done:
          return
      default:
          ch <- 1
      }
    } 
  }() 
  return ch, done
}

func main() {
  ch, done := Foo()
  <-ch
  <-ch
  done <- true
  // HERE
}
Salin selepas log masuk

Sekarang, ia nampaknya berfungsi, tetapi hanya kerana program keluar jika saya menggantikannya dengan beberapa operasi io // here(例如:http.get(“http://google.com”)) ,我面临死锁(fatal 错误:所有 goroutine 都在睡觉 - 死锁!). Saya tertanya-tanya sama ada terdapat cara lain untuk membersihkan goroutine dan saluran yang dihasilkan yang dibuat oleh fungsi foo. foo 函数创建的生成的 goroutine 和通道。


正确答案


只需在启动的 goroutine 中将 default 替换为 case

Jawapan betul

defaultCukup gantikan

dengan case dalam goroutine permulaan:
    func Foo() (<-chan int, chan<- bool) {
      ch := make(chan int)
      done := make(chan bool)
      go func() {
        defer close(ch)
        for {
          select {
          case <-done:
              return
          case ch <- 1:
          }
        } 
      }() 
      return ch, done
    }
    
    Salin selepas log masuk
  • Sebab mengapa kod asal buntu dalam situasi done 通道时,启动的写入 ch 通道的 goroutines 会立即转到 default 情况。然后 goroutine 会阻塞在 ch <- 1 行,直到其他 goroutine 从 ch adalah seperti berikut:
  • ch 读取两次。这会导致在启动的 goroutine 处有两个成功的执行循环。然后它尝试写入 done。此时启动的goroutine可能已经检查了select语句,陷入default情况并阻塞在ch <- 1行。因此主 goroutine 也会无限期地阻塞在 done <- truePenulisan yang dimulakan goroutine ke saluran ch akan segera pergi ke kes
  • apabila tiada goroutine lain yang berjalan serentak menulis ke saluran selesai. Kemudian goroutine akan menyekat pada baris ch <- 1 sehingga goroutine lain membaca nilai daripada ch. 🎜Coroutine utama dibaca daripada ch dua kali. Ini menghasilkan dua gelung pelaksanaan yang berjaya pada goroutine yang dilancarkan. Ia kemudian cuba menulis selesai. Goroutine yang bermula pada masa ini mungkin telah menyemak pernyataan select, jatuh ke dalam situasi 🎜 dan disekat pada baris ch <- 1. Oleh itu goroutine utama juga akan menyekat selama-lamanya pada baris done <- true. Ini boleh menyebabkan kebuntuan. 🎜 🎜

    Atas ialah kandungan terperinci Hentikan goroutine yang menulis ke saluran selama-lamanya. 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