Golang 채널 구현에 대해

藏色散人
풀어 주다: 2021-05-06 10:00:17
앞으로
2280명이 탐색했습니다.

다음은 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으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿