반응형

코루틴

  • 3.5 버전부터 지원(async/await 문법은 3.7 이상부터)
  • 코루틴을 사용하면 CPU와 리소스 낭비를 방지할 수 있어 I/O처리를 극대화할 수 있음
  • 일시 정지/정지가 가능한 함수를 말하며 generator 역시 코루틴에 속함

I.코루틴과 제너레이터의 차이

def generator():
    print('첫번째 작업 수행')
    yield 'first work func()'
    print('두번째 작업 수행')
    yield 'second work func()'
    print('세번째 작업 수행')
    yield 'third work func()'

gen = generator()
next(gen)
def coroutine():
    print('코루틴 시작')
    while True :
        func = yield
        print('코루틴이 신호를 받았습니다 : {}'.format(func))
        if func == 'end_func':
            try :
                print('코루틴종료') 
            except StopIteration:
                break

co = coroutine()
# yield 지점까지 서브루틴 실행, 이때 send() = None
>>> next(co)
코루틴 시작

# 값 전송 > generator 가 시작되야 가능 즉 yield까진 실행되야함
>>> co.send('first_func')
코루틴이 신호를 받았습니다 : first_func

>>> co.send('second_func')
코루틴이 신호를 받았습니다 : second_func

>>> co.send('end_func')
코루틴이 신호를 받았습니다 : end_func
코루틴종료

generator는 함수가 yield위치까지 정해진 연산을 수행하고 next()로 호출될 때마다 값을 출력하는 반복수행이 목적이지만 코루틴은 yield위치 까지 정해진 연산을 수행하고 send()를 통해 값을 송신 + 결과 출력 후 바로 다음 yield까지 작업을 수행하여 대기. 즉 외부와의 통신이 목적

II.코루틴 예시

# 코루틴 상태확인
# GEN_CREATED : 처음 대기 상태
# GEN_RUNNING : 실행상태
# GEN_SUSPENDED : yield 대기 상태
# GEN_CLOSE : 실행 완료
from inspect import getgeneratorstate 

def coroutine(x):
    print('coroutine start')
    while True :
        y = yield x
        x += y
        print('corutine receive : {}'.format(y))

co = coroutine(10)
>>> print(getgeneratorstate(co))
GEN_CREATED

# 코루팀 초기화(첫번째 yield까지 실행)
#10이 입력되었으므로 x = 10인 상태로 대기
>>> print(next(co), '\n', getgeneratorstate(co))
coroutine start
10 
 GEN_SUSPENDED

# 첫번째 send 입력
# 100이 입력되고 while문을 돌며 x + y를 수행하여 110의 값을 저장한 상태로 yield에서 대기
>>> print(co.send(100), '\n', getgeneratorstate(co))
corutine receive : 100
110 
 GEN_SUSPENDED

# 두번째 send 입력
# 200이 입력되고 while문을 이전 입력 결과인 110과 더해져 310 출력 후 yield에서 대기 
>>> print(co.send(200), '\n', getgeneratorstate(co))
corutine receive : 200
310 
 GEN_SUSPENDED

III.코루틴 vs 멀티스레드

  • 코루틴 : 싱글 스레드에서 스택을 기반으로 동작하는 비동기 동시성 작업
  • 스레드 : os에서 관리, cpu에서 실시간으로 시분할 비동기 작업으로 다수의 스레드 사용 가능

따라서 코루틴이 멀티스레드를 대체하기 위한 것은 아니며, 싱글 스레드에서 대기시간을 최소화하여 CPU의 활용을 극대화시키는 목적이다. 당연히 멀티스레드를 사용한 작업이 효율이 더 좋을것 같지만 멀티스레드 작업환경을 구성하는 것이 워낙 복잡하고 교착 상태가 발생할 가능성이 큰데다 컨텍스트 스위칭 비용이 크기 때문에 오히려 싱글쓰레드 작업이 빠른 경우가 발생하기도 한다.

** GO에서는 스레드 + 코루틴 형태의 '고루틴'을 제공하는데, 멀티스레드에서 다수의 코루틴이 한번에 실행된다. 고루틴은 프로그램 실행 시 cpu가 시분할 작업을 수행하는게 아니라 go lang 자체적으로 시분할하여 수행한다.
(관련 사항은 go 포스트 참고 => "링크")

반응형
복사했습니다!