1. 메모리 구조 차이
핸드폰 안의 프로그램을 실행시키면 메모리에 로드가 됩니다. 프로그램이 로드되면 로드 된 인스턴스를 프로세스라고 합니다. 실행된 프로세스는 여러 개의 공유된 실행의 흐름을 갖게 되는데 실행 흐름 하나 하나를 쓰레드라고 합니다. 프로세스는 자기가 사용하기 위해서 메모리 영역을 할당받는데 Heap메모리라고 합니다. 프로세스 내의 쓰레드마다도 메모리가 할당 됨 이 메모리를 Stack메모리라고 합니다. 코루틴은 쓰레드처럼 메모리를 할당 받지 않고 프로세스의 Heap메모리를 공유하고 있습니다.
2. 수행방식의 차이
코루틴은 비선점형 멀티태스킹, 쓰레드는 선점형 멀티태스킹
쓰레드는 실제로 멀티 코어를 사용해서 동일한 시간에 여러 작업을 할 수 있어 병행성이 있습니다.
반면, 코루틴은 동일한 시간에 같이 수행되지 않습니다. 코루틴이 전환되면서 수행되는 속도가 빠르기 때문에 동시에 수행되는 것 처럼 보입니다.
코루틴은 동시성은 있지만 병행성은 없습니다.
- 코루틴의 장점
만약 3개의 작업을 쓰레드에서 작업한다면 Stack영역을 모두 할당해야하지만 코루틴은 할당할 필요가 없어 사용되는 메모리가 줄어들게 됩니다.
그리고 쓰레드끼리 다른 메모리 영역에 있으므로 순서를 조정할 때 Context Switching이 일어나지만 코루틴은 Heap메모리를 공유하고 있기 때문에 Context Switching이 필요가 없어 오버헤드가 줄어들게 됩니다.
Coroutine Scope
Coroutine Context
Coroutine Builder
코루틴이 동작하는 범위를 규정
public interface CoroutineScope{
public val coroutineContext : CoroutineContext
}
스코프가 지정이 되면 특정한 CoroutineContext에서 Dispatchers를 설정해서 스코프의 영역을 제한할 수 있습니다.
Dispatchers
Dispatchers는 코루틴이 실행되는 쓰레드를 선택합니다.
Default : CPU 연산을 많이 사용하는 작업
IO : 파일 I/O 또는 네트워크 I/O
Main : UI와 관련된 변경을 해야하는 경우
Unconfined : 일반적인 용도에서 사용하지 않음
Job & Deferred
코루틴 작업을 Job이나 Deferred 로 만들어서 다루게 됩니다.
Deferred는 결과값을 반환하는 차이점이 있습니다.
val job = scope.launch{
//New Coroutine
}
Job State
launch
Job 객체 반환
async
Deferred 객체 반환
runBlocking
launch나 async는 Main쓰레드랑 관계없는 쓰레드이므로 방해하지 않습니다
runBlocking을 사용하면 Main쓰레드를 Block을 한 후에 runBlocking안의 작업을 수행하게 됩니다. 실제로는 코루틴이 아니기 때문에 코루틴을 위해서는 사용을 하지 않는 것이 좋습니다.
withContext
Dispatcher를 전환시키는 기능을 가지고 있습니다.
Dispatchers switch
Main쓰레드 내에서 작업을 하다가 IO작업이 필요한 경우 .withContext를 통해서 필요한 작업만 한 후 다시 main쓰레드를 수행할 수 있습니다.
안드로이드 OS에서 스위칭을 관리하므로 오버헤드가 줄어드니다.
레퍼런스
https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/
냉동코더의 알기 쉬운 Modern Android Developer 입문