Ce qui suit est une introduction à la mise en œuvre de la chaîne Golang à partir de la colonne tutorielle golang. J'espère que cela sera utile aux amis dans le besoin !
1. Introduction
Le canal est la méthode de communication entre les goroutines fournie par le langage Go au niveau du langage. Les canaux peuvent être utilisés pour transmettre des messages entre deux ou plusieurs goroutines. Le canal est une méthode de communication intra-processus, de sorte que le processus de transmission d'objets via des canaux est cohérent avec le comportement de transmission des paramètres lors de l'appel de fonctions. Par exemple, des pointeurs peuvent également être transmis. Si une communication entre processus est requise, il est recommandé d'utiliser un système distribué pour résoudre le problème, par exemple en utilisant des protocoles de communication tels que Socket ou HTTP.
Le canal est lié au type, c'est-à-dire qu'un canal ne peut transmettre qu'un seul type de valeur, et ce type doit être spécifié lors de la déclaration du canal. Notez que le canal lui-même est également un type natif dans le langage Go, avec le même statut que les types tels que map, de sorte que le canal lui-même peut également être transmis via le canal après avoir été défini.
2. Implémentation sous-jacente
2.1 hchan structure
type hchan struct {
qcount uint // 队列中当前数据的个数
dataqsiz uint // size of the circular queue
buf unsafe.Pointer // 数据缓冲区,存放数据的环形数组
elemsize uint16 // channel中数据类型的大小(单个元素的大小)
closed uint32 // 表示channel是否关闭标识位
elemtype *_type // 队列中的元素类型
sendx uint // 当前发送元素的索引
recvx uint // 当前接收元素的索引
recvq waitq // 接受等待队列,由recv行为(也就是<-ch)阻塞在channel上的goroutine队列
sendq waitq // 发送等待队列, 由send行为(也就是ch<-)阻塞在channel上的goroutine队列
//lock保护chann中的所有字段,以及在此通道上阻塞的sudoG中的几个字段。
//保持此锁时不要更改另一个G状态(特别是没准备好G),因为这可能会因堆栈收缩而死锁
lock mutex
}
//发送及接收队列的·1结构体
type waitq struct {
first *sudog
last *sudog
}
-
qcount uint // Le nombre d'éléments restant dans la file d'attente actuelle.
-
dataqsiz uint // Longueur de la file d'attente en anneau, c'est-à-dire la taille du tampon, c'est-à-dire make(chan T, N), N.
-
buf unsafe.Pointer // Pointeur de file d'attente en anneau.
-
elemsize uint16 // La taille de chaque élément.
-
fermé uint32 // Indique si le canal actuel est fermé. Lorsqu'un canal est créé, ce champ est mis à 0, ce qui signifie que le canal est ouvert ; en le mettant à 1 en appelant close, le canal est fermé.
-
elemtype *_type // Type d'élément, utilisé pour l'affectation lors du transfert de données.
-
sendx uint et recvx uint sont les champs d'état du tampon en anneau, qui indiquent l'index actuel du tampon - prend en charge les tableaux à partir desquels il peut envoyer et recevoir données .
-
recvq waitq // File d'attente Goroutine en attente de lecture des messages.
-
sendq waitq // File d'attente Goroutine en attente d'écriture de messages.
-
lock mutex // Mutex lock, verrouille le canal pour chaque opération de lecture et d'écriture, car l'envoi et la réception doivent être des opérations mutuellement exclusives.
2.2 Processus de création
2.2.1 Opération d'écriture
1 Créer un canal avec tampon
2. Écrivez les données sur le canal
3.3 Processus d'écriture Comme suit :
Verrouillez toute la structure du tuyau. - Confirmez l'écriture, essayez d'attendre la goroutine de la file d'attente, puis écrivez l'élément directement dans la goroutine.
- Si recvq est vide, déterminez si le tampon est disponible. Si disponible, copie les données de la goroutine actuelle vers le tampon.
- Si le tampon est plein, l'élément à écrire sera enregistré dans la structure goroutine en cours d'exécution, et la goroutine actuelle sera mise en file d'attente dans sendq et suspendue de son exécution.
- L'écriture est terminée et le verrou est libéré.
-
2.2.2 Processus de lecture
Lisez d'abord le verrouillage global du canal. - Essayez sendq pour récupérer la goroutine en attente de la file d'attente.
- S'il y a une goroutine en attente et un tampon (le tampon est plein), prenez les données de la tête de la file d'attente du tampon, puis retirez une goroutine de sendq. Stockez les données dans la goroutine dans le bit buf et terminez la lecture pour libérer le verrou.
- S'il n'y a pas de goroutine en attente et qu'il y a des données dans le tampon, lisez directement les données du tampon et expliquez le verrou de libération de lecture.
- S'il n'y a pas de goroutine en attente, qu'il n'y a pas de tampon ou que la zone tampon est vide, ajoutez la goroutine actuelle à la file d'attente denq, entrez en veille et attendez d'être réveillé en écrivant goroutine. Terminez de déverrouiller le verrou.
-
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!