golang 의 select 실현 원리 분석

3342 단어
맨 앞 에 써 주세요.
select 는 golang 에 다 중 IO 재 활용 체 제 를 제공 합 니 다. 다른 IO 재 활용 과 마찬가지 로 읽 기와 쓰기 이벤트 가 ready 되 었 는 지 확인 하 는 데 사 용 됩 니 다.
본 고 는 골 랑 의 select 의 용법 과 실현 원 리 를 소개 할 것 이다.
실현 원리
golang 이 select 를 실현 할 때 실제 적 으로 모든 case 문 구 를 하나의 데이터 구 조 를 정의 합 니 다. selection 문 구 를 실행 할 때 실제 적 으로 하나의 case 배열 로 처 리 된 코드 블록 (또는 함수) 을 비교 한 다음 에 프로그램 절 차 는 선택 한 case 블록 으로 이동 할 수 있 습 니 다.
케이스 데이터 구조
소스 패키지 src/runtime/select.go:scase 는 case 문 구 를 나타 내 는 데이터 구 조 를 정의 했다.
type scase struct {
	c           *hchan         // chan
	kind        uint16
	elem        unsafe.Pointer // data element
}

scase. c 는 현재 case 문 구 를 조작 하 는 chan 지침 을 표시 합 니 다. 이것 은 하나의 case 가 하나의 chan 만 감청 할 수 있 음 을 나타 냅 니 다.
scase. kind 는 현재 chan 이 읽 을 수 있 는 지, 쓸 수 있 는 channel 또는 default 인지 표시 합 니 다.세 가지 유형 은 각각 상수 로 정의 된다.
  • caseRecv: case 문장 에서 scase. c 의 데 이 터 를 읽 으 려 고 시도 합 니 다.
  • case send: case 문장에서 scase. c 에 데 이 터 를 기록 하려 고 시도 합 니 다.
  • caseDefault: default 문장
  • scase. elem 은 버퍼 주 소 를 표시 합 니 다. scase. kind 와 달리 용도 가 다 릅 니 다.
  • scase. kind = = caseRecv: scase. elem 은 channel 을 읽 는 데이터 저장 주 소 를 표시 합 니 다.
  • scase. kind = = caseSend: scase. elem 은 channel 에 쓸 데이터 저장 주 소 를 표시 합 니 다.

  • select 실현 논리
    원본 패키지 src/runtime/select.go:selectgo() 는 select 선택 case 의 함 수 를 정의 합 니 다.
    // selectgo implements the select statement.
    //
    // *sel is on the current goroutine's stack (regardless of any
    // escaping in selectgo).
    //
    // selectgo returns the index of the chosen scase, which matches the
    // ordinal position of its respective select{recv,send,default} call.
    func selectgo(sel *hselect) int {
    }

    그 중에서 데이터 구조 hselect 는 다음 과 같다.
    // Select statement header.
    // Known to compiler.
    // Changes here must also be made in src/cmd/internal/gc/select.go's selecttype.
    type hselect struct {
    	tcase     uint16   // total count of scase[]
    	ncase     uint16   // currently filled scase[]
    	pollorder *uint16  // case poll order
    	lockorder *uint16  // channel lock order
    	scase     [1]scase // one per case (in order of appearance)
    }
    

    hselect. tcase 에 저 장 된 것 은 scase 총수 입 니 다.
    hselect. pollorder 는 scase 의 무 작위 적 인 배열 을 저장 합 니 다.무 작위 검사 케이스 의 목적 을 달성 하 다.
    hselect. lockorder 는 저 장 된 channel 주소 입 니 다.모든 case 구문 에서 channel 서열 은 channel 에 자 물 쇠 를 추가 할 때 반복 적 으로 자 물 쇠 를 추가 하 는 것 을 방지 하 는 목적 을 달성 합 니 다.
    selectgo 는 int 로 돌아 가 선택 한 scase, 즉 ready 의 channel index 를 표시 합 니 다.
    이 함수 의 실행 논 리 는 대체로 다음 과 같다.
    1. scase 문장의 모든 channel 잠 금
    2. 무 작위 순서 로 scase 의 channel ready 여 부 를 검사 합 니 다.
    2.1 case 가 읽 을 수 있다 면 channel 의 데 이 터 를 읽 고 모든 channel 을 잠 그 고 되 돌려 줍 니 다 (case index)
    2.2 case 가 쓸 수 있다 면 데 이 터 를 channel 에 기록 하고 모든 channel 의 잠 금 을 풀 고 되 돌려 줍 니 다 (case index)
    2.3 모든 case 가 ready 되 지 않 으 면 모든 channel 을 잠 그 고 되 돌려 줍 니 다 (default index)
    3. 모든 케이스 가 준비 되 지 않 았 고 default 문구 가 없습니다.
       3.1 현재 협 정 을 모든 channel 대기 열 에 추가 합 니 다.
     3.2 협 정 을 차단 으로 전환 하고 깨 어 날 때 까지 기다린다.
    4. 각성 후 채널 에 대응 하 는 case index 로 되 돌아 가기
    4.1 읽 기 동작 이 라면 모든 channel 을 잠 그 고 되 돌려 줍 니 다 (case index)
    4.2 쓰기 동작 이 라면 모든 channel 을 잠 그 고 되 돌려 줍 니 다 (case index)

    좋은 웹페이지 즐겨찾기