Maison >développement back-end >Golang >Arrêtez indéfiniment une goroutine qui écrit sur un canal

Arrêtez indéfiniment une goroutine qui écrit sur un canal

WBOY
WBOYavant
2024-02-05 23:09:07944parcourir

停止无限期写入通道的 goroutine

Contenu de la question

J'ai une fonction qui crée une goroutine qui remplit un canal indéfiniment, par exemple :

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

Supposons que nous ayons un consommateur que nous souhaitons arrêter après un certain temps :

ch:=foo() 
<-ch
<-ch
// done

Maintenant, je souhaite nettoyer les ressources goroutine, y compris les chaînes. J'ai essayé d'ajouter un canal « achèvement » pour cela, mais je me suis ensuite retrouvé dans une impasse :

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
}

Maintenant, cela semble fonctionner, mais uniquement parce que le programme se termine si je le remplace par quelques opérations io // here(例如:http.get(“http://google.com”)) ,我面临死锁(fatal 错误:所有 goroutine 都在睡觉 - 死锁!). Je me demande s'il existe un autre moyen de nettoyer les goroutines et les canaux générés par la fonction foo. foo 函数创建的生成的 goroutine 和通道。


正确答案


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

Bonne réponse

defaultRemplacez simplement

par case dans la goroutine de départ :
    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
    }
    
  • La raison pour laquelle le code d'origine est bloqué dans la situation done 通道时,启动的写入 ch 通道的 goroutines 会立即转到 default 情况。然后 goroutine 会阻塞在 ch <- 1 行,直到其他 goroutine 从 ch est la suivante :
  • ch 读取两次。这会导致在启动的 goroutine 处有两个成功的执行循环。然后它尝试写入 done。此时启动的goroutine可能已经检查了select语句,陷入default情况并阻塞在ch <- 1行。因此主 goroutine 也会无限期地阻塞在 done <- trueUne goroutine initiée en train d'écrire sur un canal ch ira immédiatement au cas
  • lorsqu'aucune autre goroutine exécutée simultanément n'écrit sur le canal done. La goroutine bloquera alors sur la ligne ch <- 1 jusqu'à ce qu'une autre goroutine lise la valeur de ch.
🎜La coroutine principale lit deux fois depuis ch. Cela se traduit par deux boucles d'exécution réussies au niveau de la goroutine lancée. Il tente ensuite d'écrire done. La goroutine démarrée à ce moment-là a peut-être vérifié l'instruction select, est tombée dans la situation 🎜 et s'est bloquée sur la ligne ch <- 1. Par conséquent, la goroutine principale bloquera également indéfiniment sur la ligne done <- true. Cela peut conduire à une impasse. 🎜 🎜

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer