새소식

android studio

[Android] Thread와 Coroutine의 차이

  • -

프로젝트를 진행하다보면 비동기 처리를 위해 사용되는 라이브러리들이 많은데 비동기처리의 주 "코루틴" 에 대해서 공부하다보니, thread? coroutine? 비슷한 작동방식이 아닌가라는 생각이 들었다. 

그래서 쓰레드와 코루틴이 정확히 무엇인지 비교를 해보려고 한다. 

 

먼저 Thread와 Coroutine은 모두 동시성 프로그래밍을 위한 기술이다. 

 

동시성과 병렬성(Concurrency & Parallelism)

동시성 (Concurrency)

말 그대로 동시에 여러 작업을 수행하는 것

 

 

Task1과 Task2를 시분할(Interleaving) 기법을 활용하여 동시에 실행되는 것처럼 번갈아가며 수행한다. 

수행시간은 Task1이 걸리는 시간 10분 + Task2가 걸리는 시간 10분 =  총 20분이 소요된다. 

 

 

병렬성 (Parallelism)

여러 작업을 한 번에 동시에 수행하는 것
병렬성은 '자원(CPU 코어)이 여러 개' 일 때 가능

동시성과 달리 하나의 CPU 코어에서 Task들이 실행되는 것이 아니라  각 Task는 각 CPU에 배분되어 병렬적으로 동시에 수행된다. 

따라서 각 Task들은 10분씩 걸린다고 가정하였으므로 수행시간은 총 10분이 소요된다. 

 

 

💡 Thread vs Coroutine

  • Thread는 각 태스크에 해당하는 스택 메모리를 할당받는다.
  • 그리고 여러 작업을 동시에 수행해야할 때 OS 는 어떤 쓰레드 작업을 먼저 수행할지, 어떤 쓰레드를 더 많이 수행해야 효율적인지에 대한 스케쥴링 (선점 스케쥴링) 을 해야 한다.

 

  • Coroutuine  Lightweight Thread 라고 부른다.
  • 마찬가지로 작업 하나하나를 효율적으로 분배해서 동시성을 보장하는 것을 목표로 하지만, 작업 하나하나에     Thread 를 할당하는 것이 아닌 '객체' 를 할당해주고, 이 객체를 자유롭게 스위칭함으로써 Context Switching 비용을 대폭 줄인 것이다.

 

Thread

1. 작업(Task) 하나하나의 단위 : Thread

  • 각 Thread 가 독립적인 Stack 메모리 영역 가짐

2.  동시성 보장 수단 : Context Switching

  • 운영체제 커널에 의한 Context Switching 을 통해 동시성 보장
  • 블로킹 (Blocking) : Thread A 가 Thread B 의 결과가 나오기까지 기다려야 한다면, Thread A 은 블로킹되어 Thread B 의 결과가 나올 때 까지 해당 자원을 못 씀

 

Thread A 에서 Task 1 을 수행하다가 Task 2 의 결과가 필요할 때, 비동기적으로 Thread B 를 호출을 하게 된다. 이 때 Thread A 는 블로킹되고, Thread B 로 Context Switching 이 일어나 Task 2 를 수행한다. Task 2 가 완료되면, 다시 Thread A 로 Context Switching 이 일어나 결과값을 Task 1 에 반환한다.

동시에 같이 수행할 Task 3, Task 4 는 각각 Thread C 와 D  할당되고, 총체적으로 봤을 때 커널 입장에서 Preempting Scheduling 을 통하여 각 태스크를 얼만큼 수행할지, 혹은 무엇을 먼저 수행할지를 결정하여 알맞게 동시성을 보장하게 되는 것이다.

Coroutine

1. 작업 하나하나의 단위 : Coroutine Object

  • 여러 작업 각각에 Object 를 할당함
  • Coroutine Object 도 엄연한 객체이기 때문에 JVM Heap 에 적재 됨 (코틀린 기준)

2. 동시성 보장 수단 : Programmer Switching (No-Context Switching)

  • 프로그래머의 코드를 통해 Switching 시점을 마음대로 정함 (OS 관여 X)
  • Suspend (Non-Blocking) : Object 1 이 Object 2 의 결과가 나오기까지 기다려야 한다면, Object 1 은 Suspend(중단) 되지만, Object 1 을 수행하던 Thread 는 그대로 유효하기 때문에 Object 2 도 Object 1 과 동일한 Thread 에서 실행될 수 있음

 

작업 단위는 Coroutine Object 이므로, Task 1 을 수행하다가 비동기 작업 Task 2 가 발생하더라도, Context Switching 없이 같은 Thread 에서 Task 2 를 수행할 수 있고, 맨 오른쪽 경우처럼 하나의 Thread 에서 여러 Coroutine Object 들을 같이 수행할 수도 있다. 한 쓰레드에서 다수의 Coroutine 을 수행할 수 있고, Context Switching 이 필요없는 특성에 따라 Coroutine 을 Light-weight Thread 라고 부르는 것이다.

 

(그런데 맨 오른쪽 그림처럼 Thread A 와 C 가 동시에 수행되는 모습이다. 이러면 결국 동시성 보장을 위해서 Context Switching 이 필요한 경우다. 따라서, Coroutine 의 'No-Context Switching' 장점을 극강으로 끌어올리기 위해, 단일 Thread 에서 여러 Coroutine Object 를 컨트롤하는 것이 좋다.)

 

 

 

 

💡  Coroutine 은 Thread 의 대안이 아니라, Thread 를 더 잘게 쪼개어 사용하기 위한 개념이다.

  • 작업의 단위를 Object 로 축소하면서 하나의 Thread 다수의 코루틴을 다룰 수 있기 때문에, 작업 하나하나에 Thread 를 할당하며 메모리 낭비, Context Switching 비용 낭비를 할 필요가 없음

 

 

🤨 주요 개념

코루틴에 대해 이해하기 위해서 기본적으로 알아야 하는 개념

CoroutineScope

CoroutineContext (Job, Dispatchers)

CoroutineBuilder (launch, async)

susfend function

 

 


참고자료 :  https://velog.io/@haero_kim/Thread-vs-Coroutine-%EB%B9%84%EA%B5%90%ED%95%B4%EB%B3%B4%EA%B8%B0

Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.