>백엔드 개발 >Golang >Golang 채널 구현에 대해

Golang 채널 구현에 대해

藏色散人
藏色散人앞으로
2021-05-06 10:00:172342검색

다음은 golang 튜토리얼 칼럼에서 Golang 채널 구현에 대한 소개입니다. 도움이 필요한 친구들에게 도움이 되길 바랍니다!

1. 소개

채널은 언어 수준에서 Go 언어가 제공하는 고루틴 간의 통신 방법입니다. 채널은 두 개 이상의 고루틴 간에 메시지를 전달하는 데 사용할 수 있습니다. 채널은 프로세스 내 통신 방법이므로 채널을 통해 객체를 전달하는 프로세스는 함수 호출 시 매개변수 전달 동작과 일치합니다. 예를 들어 포인터도 전달할 수 있습니다. 프로세스 간 통신이 필요한 경우 소켓이나 HTTP와 같은 통신 프로토콜을 사용하는 등 분산 시스템을 사용하여 문제를 해결하는 것이 좋습니다.

채널은 유형과 관련되어 있습니다. 즉, 채널은 한 가지 유형의 값만 전달할 수 있으며 채널을 선언할 때 이 유형을 지정해야 합니다. 채널 자체도 Go 언어의 기본 유형이며 지도와 같은 유형과 동일한 상태이므로 채널 자체도 정의된 후 채널을 통해 전달될 수 있습니다.

2. 기본 구현

2.1 hchan 구조

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 // 현재 대기열에 남아 있는 요소 수입니다.
  • dataqsiz uint // 링 큐 길이, 즉 버퍼의 크기, 즉 make(chan T, N), N.
  • buf unsafe.Pointer // 링 큐 포인터.
  • elemsize uint16 // 각 요소의 크기입니다.
  • closed uint32 // 현재 채널이 닫혀 있는지 여부를 나타냅니다. 채널이 생성되면 이 필드는 0으로 설정됩니다. 즉, close를 호출하여 1로 설정하면 채널이 닫힙니다.
  • elemtype *_type // 데이터 전송 중 할당에 사용되는 요소 유형입니다.
  • sendx uint 및 recvx uint는 링 버퍼의 상태 필드로, 버퍼의 현재 인덱스를 나타내며 데이터를 보내고 받을 수 있는 배열을 지원합니다.
  • recvq waitq // 메시지 읽기를 기다리는 고루틴 큐.
  • sendq waitq // 메시지 쓰기를 기다리는 고루틴 큐.
  • lock mutex // 뮤텍스 잠금은 전송 및 수신이 상호 배타적인 작업이어야 하기 때문에 읽기 및 쓰기 작업마다 채널을 잠급니다.

2.2 생성 과정

2.2.1 쓰기 작업

1. 버퍼로 채널을 생성합니다

2. 채널에 데이터를 씁니다

3.3 항목 쓰기 프로세스는 다음과 같습니다.

  • 전체 파이프라인 구조를 잠급니다.
  • 쓰기를 확인하고 대기열에서 고루틴을 기다린 다음 요소를 고루틴에 직접 씁니다.
  • recvq가 비어 있으면 버퍼를 사용할 수 있는지 확인하세요. 가능한 경우 현재 고루틴의 데이터를 버퍼에 복사합니다.
  • 버퍼가 가득 차면 쓸 요소는 현재 실행 중인 고루틴 구조에 저장되고, 현재 고루틴은 sendq의 대기열에 추가되어 실행이 일시 중지됩니다.
  • 쓰기가 완료되고 잠금이 해제됩니다.

2.2.2 읽기 과정

  • 먼저 채널 글로벌 잠금을 읽어보세요.
  • sendq를 사용해 대기 대기열에서 대기 중인 고루틴을 가져오세요.
  • 대기 중인 고루틴과 버퍼(버퍼가 가득 찼음)가 있으면 버퍼 큐의 헤드에서 데이터를 가져온 다음 sendq에서 고루틴을 꺼냅니다. 고루틴의 데이터를 buf 비트에 저장하고 읽기를 종료하여 잠금을 해제합니다.
  • 대기 중인 고루틴이 없고 버퍼에 데이터가 있는 경우 버퍼 데이터를 직접 읽고 읽기 해제 잠금을 설명합니다.
  • 대기 중인 고루틴이 없고 버퍼가 없거나 버퍼 영역이 비어 있는 경우 현재 고루틴을 denq 대기열에 추가하고 절전 모드로 들어간 후 고루틴을 작성하여 깨어나기를 기다립니다. 잠금 해제를 완료합니다.

위 내용은 Golang 채널 구현에 대해의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 csdn.net에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제