코틀린의 코루틴 이해하기 위한 실험

코틀린의 코루틴은 병렬 프로그래밍을 손쉽게해주는 효과적인 도구이다. 이런 코루틴을 잘 이해하고자 몇가지 실험을 해봤다. 기본적인 코틀린 코루틴에 대한 사용법을 아셔야 내용을 이해할 수 있을 것이다.

스레드 기반의 병렬 프로그래밍

일반적인 스레드는 선점형(Preemptive)이다. 선점형이란 말은 여러 스레드가 서로 자기가 실행되기 위해 싸운다는 의미이다. 아래 예제에서는 두 스레드가 서로 1과 2를 출력한다.

서로 다른 두 스레드가 돌아가며 실행되기 때문에 1과 2가 번갈아서 출력된다. 한번 Context Switching이 일어나면 한 스레드가 계속실행되다가 다른 스레드로 넘어가는 걸 볼 수 있다. 코루틴을 이용한 비슷한 예시를 만들어봤다. 하지만 결과는 많이 차이가 난다.

같은 스레드 안의 코루틴들은 기본적로는 스레드처럼 선점을 하려고 하지 않는다. 한 코루틴이 끝나면 그 스레드에 있는 다른 코루틴이 실행된다. 따라서 스레드처럼 병렬적으로(Parallel) 실행되지 않는다. 코루틴은 동시적(Concurrency)인 방식이다.

runBlocking{} 은 해당 스레드에서 코루틴을 실행하고 코루틴이 종료할 때까지 스레드를 블로킹한다. 때문에 위 코드에선 join()을 하지 않아도 프로그램이 종료되지 않는다. launch()로 만들어진 코루틴이 runBlocking()과 같은 스레드에 속해있기 때문에, runBlocking()은 launch() 작업이 끝날 때까지 기다리게된다.

동시프로그래밍

내가 처음 코루틴을 사용할 때 코루틴은 병렬 프로그래밍을 쉽고 간편하게 해줄 수 있는 모듈이라고 생각했다. 하지만 실제로 코루틴은 협력적(Cooperative)으로 동작하는 동시프로그래밍(Concurrency Programming) 방식이다.

동시 프로그래밍에선 실제로는 한 번에 하나만 동작하지만, 흐름을 빠르게 나누어 실행하며 마치 여러 프로그램이 동시에 동작하는 것처럼 보이게 한다. 멀티스레드 환경에선 OS가 일정 시점에서 흐름을 끊지만, 코루틴은 프로그램이 블로킹되는 지점에서 흐름을 끊는다.

delay()같은 함수를 이용해서 지정된 시간동안 정지할 수도 있고, 파일 입출력, 네트워크 I/O 등에 의해서도 다른 코루틴이 실행되게 된다.

위 예시에서 첫 코루틴은 1ms만 멈추길 원했지만 두번째 코루틴이 긴 시간동안 계속 스레드를 점유하고 있었기 때문에 첫번째 코루틴은 훨씬 긴 시간(3초)를 기다리게 된다.

Image for post
Image for post

참고로 delay()는 코루틴을 블록시키는 함수이기 때문에 Thread.sleep()을 사용하면 코루틴의 스위칭이 발생하지 않는다. 또한 코루틴의 delay 혹은 join같은 함수는 suspend modifier로 정의되어있다. 이런 suspend함수는 launch() async()같은 코루틴 내부 혹은 suspend 함수 내부에선 호출되도록 제약이 걸려있다.

코루틴으로 병렬 프로그래밍

멀티스레드 기반의 병렬 프로그래밍을 목표로 코루틴을 사용한다고 하면 위와 같은 특징 때문에 내가 의도한 대로 프로그램이 실행되지 않을 수 있다. 하지만 위와 같은 특성 덕분에 코루틴은 기존의 스레드 위에서 빠르게 동시프로그래밍을 구현할 수 있다. 스레드를 생성하는게 아니기 때문에 스레드 생성에 들어가는 메모리를 절약할 수 있다. 하지만 코루틴이 항상 스레드보다 빠르진 않다. 빠를 수도 느릴 수도 있다고 한다.

스레드 풀을 이용해서 코루틴을 병렬적으로 이용할 수도 있다. GlobalScope를 이용해서 코루틴을 실행하면 기본적으로 Java의 ForkJoinPool의 스레드에서 코루틴이 실행된다. 또 스레드 풀을 직접 만들어서 사용할 수도 있다. 단 이경우 코루틴 스레드가 살아있어도 다른 스레드가 종료되면 프로그램이 종료된다.

위의 예제는 GlobalScope를 이용해서 기본 스레드풀에서 코루틴을 실행한 예제이다. 마치 스레드를 쓴 것처럼 번갈아가며 결과가 표시된다.

코루틴은 중간에 취소도 가능하고, launch 대신 async를 써서 결과값을 받을 수도 있다. 또 이부분은 실험중인데 코루틴에서 예외가 발생하면 스레드까지 바로 죽어버리는 것 같다.

참고글

Written by

2020.12.8 ~ 2022.6.9 군복무중 Serving in the South Korean Military Service

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store