Python 3 튜 토리 얼 - 협 정 (료 설 봉 공식 홈 페이지 에서 전환)

6839 단어 Python
비동기 IO 모델 을 배우 기 전에 협 정 을 알 아 보 겠 습 니 다.
협 정영어 이름 Corontine.
협 정의 개념 은 일찍부터 제기 되 었 으 나 최근 몇 년 에 야 일부 언어 (예 를 들 어 Lua) 에서 광범 위 하 게 응용 되 었 다.
서브루틴 또는 함수 라 고 부 릅 니 다. 모든 언어 에서 등급 호출 입 니 다. 예 를 들 어 A 호출 B, B 는 실행 과정 에서 C, C 실행 이 끝나 고 돌아 갑 니 다. B 실행 이 끝나 고 돌아 갑 니 다. 마지막 으로 A 실행 이 끝 났 습 니 다.
그래서 서브루틴 호출 은 스 택 을 통 해 이 루어 집 니 다. 하나의 스 레 드 는 하위 프로그램 을 실행 하 는 것 입 니 다.
서브루틴 호출 은 항상 하나의 입구 이 고 한 번 에 되 돌아 오 며 호출 순 서 는 명확 합 니 다.협 정의 호출 은 서브루틴 과 다르다.
협 정 도 서브루틴 으로 보이 지만 실행 과정 에서 서브루틴 내부 에서 중단 되 고 다른 서브루틴 을 실행 하 며 적당 한 시기 에 되 돌아 와 서 실행 할 수 있 습 니 다.
한 하위 프로그램 에서 중단 되 고 다른 하위 프로그램 을 실행 하 십시오. 함수 호출 이 아니 라 CPU 의 중단 과 유사 합 니 다.예 를 들 어 서브루틴 A, B:
def A():
    print('1')
    print('2')
    print('3')

def B():
    print('x')
    print('y')
    print('z')

만약 에 협 정 에 의 해 집행 된다 고 가정 하면 A 를 집행 하 는 과정 에서 수시로 중단 할 수 있 고 B 를 집행 할 수 있 으 며 B 는 집행 과정 에서 중단 하고 A 를 집행 할 수 있 습 니 다. 결 과 는 다음 과 같 을 수 있 습 니 다.
1
2
x
y
3
z

그러나 A 에 서 는 B 를 호출 하지 않 았 기 때문에 협 정의 호출 은 함수 호출 보다 이해 하기 어렵다.
보기에 A, B 의 집행 은 약간 다 중 스 레 드 와 같 지만 협 정의 특징 은 하나의 스 레 드 집행 이다. 그것 은 다 중 스 레 드 와 비교 하면 협 정 은 어떤 장점 이 있 습 니까?
가장 큰 장점 은 협정 이 매우 높 은 집행 효율 이다.서브루틴 전환 은 스 레 드 전환 이 아니 라 프로그램 자체 가 제어 하기 때문에 스 레 드 전환 비용 이 없고 다 중 스 레 드 와 비교 할 때 스 레 드 수량 이 많 을 수록 협 정의 성능 장점 이 뚜렷 합 니 다.
두 번 째 장점 은 다 중 스 레 드 의 잠 금 체 제 를 필요 로 하지 않 는 다 는 것 이다. 하나의 스 레 드 만 있 고 변수 충돌 도 존재 하지 않 기 때문에 협 정 에서 공유 자원 을 제어 하고 자 물 쇠 를 추가 하지 않 으 며 상 태 를 판단 하면 되 기 때문에 집행 효율 이 다 중 스 레 드 보다 훨씬 높다.
협 정 은 하나의 스 레 드 로 실행 되 기 때문에 다 핵 CPU 를 어떻게 이용 합 니까?가장 간단 한 방법 은 다 중 프로 세 스 + 협 정 으로 다 핵 을 충분히 이용 할 뿐만 아니 라 협 정의 효율 도 충분히 발휘 하여 높 은 성능 을 얻 을 수 있다.
Python 의 협 정 에 대한 지 지 는 generator 를 통 해 이 루어 졌 다.
generator 에서 우 리 는 for 순환 을 통 해 교체 할 수 있 을 뿐만 아니 라 next () 함수 도 계속 호출 하여 yield 구문 에서 돌아 오 는 다음 값 을 얻 을 수 있 습 니 다.
그러나 Python 의 yield 는 값 을 되 돌려 줄 뿐만 아니 라 호출 자가 보 낸 인자 도 받 을 수 있 습 니 다.
보기 예:
전통 적 인 생산자 - 소비자 모델 은 하나의 스 레 드 로 메 시 지 를 쓰 고 하나의 스 레 드 로 메 시 지 를 얻 으 며 잠 금 체 제 를 통 해 대기 열 을 제어 하지만 조심 하지 않 으 면 잠 금 이 사라 질 수 있 습 니 다.
만약 에 협 정 을 바 꾸 면 생산자 가 생산 정 보 를 생산 한 후에 yield 를 통 해 소비자 에 게 직접 전달 하여 집행 하기 시작 하고 소비자 가 집행 이 끝 난 후에 생산자 로 전환 하여 계속 생산 하면 효율 이 매우 높다.
def consumer():
    r = ''
    while True:
        n = yield r
        if not n:
            return
        print('[CONSUMER] Consuming %s...' % n)
        r = '200 OK'

def produce(c):
    c.send(None)
    n = 0
    while n < 5:
        n = n + 1
        print('[PRODUCER] Producing %s...' % n)
        r = c.send(n)
        print('[PRODUCER] Consumer return: %s' % r)
    c.close()

c = consumer()
produce(c)

실행 결과:
[PRODUCER] Producing 1...
[CONSUMER] Consuming 1...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 2...
[CONSUMER] Consuming 2...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 3...
[CONSUMER] Consuming 3...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 4...
[CONSUMER] Consuming 4...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 5...
[CONSUMER] Consuming 5...
[PRODUCER] Consumer return: 200 OK

consumer 함수 가 generator 라 는 것 을 알 고 consumer 를 produt 에 전송 한 후:
먼저 c. send (None) 를 호출 하여 생 성 기 를 시작 합 니 다.
그리고 물건 을 생산 하면 c. send (n) 를 통 해 consumer 로 전환 합 니 다.
consumer 는 yield 를 통 해 정 보 를 얻 고 처리 하 며 yield 를 통 해 결 과 를 전달 합 니 다.
produt 는 consumer 처리 결 과 를 얻 고 다음 소식 을 계속 생산 합 니 다.
produce 는 생산 을 하지 않 기로 결 정 했 습 니 다. c. close () 를 통 해 consumer 를 닫 고 전체 과정 이 끝 났 습 니 다.
전체 프로 세 스 가 잠 겨 있 지 않 고 하나의 스 레 드 에서 실 행 됩 니 다. produt 와 consumer 가 합작 하여 임 무 를 완성 하기 때문에 스 레 드 의 선점 식 다 중 임무 가 아 닌 '협 정' 이 라 고 부 릅 니 다.
마지막 으로 Donald Knuth 의 한 마디 로 협 정의 특징 을 요약 한다.
"서브루틴 은 협 정의 특례 이다."
(나 소 진) 개인 적 으로 이것 은 귀환 과 완전히 다르다 고 생각한다.재 귀 는 자신 이 자신 을 호출 하 는 것 으로 많은 스 택 공간 자원 을 사용 합 니 다.협 정 은 두 함수 (본 튜 토리 얼 의 예, 다른 호출 가능 한 동 동) 사 이 를 오 가 며 전환 할 수 있 을 것 입 니 다. 두 함수 의 변 수 는 스 택 과 스 택 을 교체 하여 스 택 이 넘 치지 않도록 해 야 합 니 다.사실은 다 중 스 레 드 전환 과 유사 하지만 이것 은 스 레 드 사이 에서 전환 하 는 것 이 아니 라 같은 스 레 드 안의 함수 사이 에서 전환 하 는 것 입 니 다. 전환 속도 가 빠 르 고 자주 전환 해 야 하 며 데이터 양 이 매우 큰 장면 이 아 닙 니 다.이상 은 개인의 약간의 이해 이 므 로 옳 고 그 름 을 모른다.

좋은 웹페이지 즐겨찾기