[Android] 멀티태스킹과 Context-Switching

Twaun·2022년 7월 19일
0

Android

목록 보기
13/24

멀티 태스킹이란?

멀티 태스킹이란 동시에 여러 작업을 하는 것을 말한다.

이를 개발자 시선에서 보자면 중앙 처리 장치(CPU)가 여러 작업을 하기위해 공용 자원을 사용하는 것을 말한다. 여기서 공용 자원은 '시간'이 된다.

하지만!! 여기서 문제가 있다. CPU는 한번에 하나의 작업만 가능하다. 즉, 여러 작업을 각각 시간을 부여하고 부여받은 시간만큼 교대로 작업을 한다. 이러한 교대 작업이 사용자는 마치 동시에 작업을 하는 것처럼 느껴지는 것이다.

여기서 중요한 키워드는 '교대 작업' 이다. 이와 같이 여러 프로세스들이 특정 시간만큼 번갈아가며 실행하는 것을 Context Switching이라고 한다.

Context Switching

더 정확히 말하자면 현재 CPU에서 작업중인 프로세스와 다음 진행할 프로세스를 관리하는 PCB(Process Control Block) 사이에 프로세스를 교체해주는 작업이 Context Switching 이다.

특징

  1. Interrupt
    : Context Switching 과정에서 프로세스의 중단과 실행사이에 발생하는 공백.
  2. 오버헤드
    : 프로세스 실행을 위한 부가적인 활동, 부담 비용.
  3. 시간 할당량
    : 각 프로세스가 CPU에서 할당받은 시간.

시간 할당량에 따른 특징

시간 할당량 ⬆️시간 할당량 ⬇️
Context Switching적음많음
인터럽트 발생적음많음
멀티 태스킹느린 느낌빠른 느낌

시간 할당량이 많으면 그만큼 하나의 작업 시간이 길고 그만큼 교체가 천천히 일어나므로 Context Switching과 인터럽트는 적어지는 반면 멀티 태스킹이 잘 안되는 느낌이 들 것이다. 반면에 시간 할당량이 적으면 교체가 빠르게 빠르게 일어나 멀티 태스킹이 잘되는 느낌이 들지만 Context Switching과 인터럽트는 많아질 것이다.

위와 같은 특징을 고려해서 적절한 시간 할당량을 부여해서 효율적인 멀티 태스킹이 일어나도록 하기 위해서 프로세스들을 특정 우선순위를 기반으로 CPU를 할당받게 하는 것이 스케쥴러(Scheduler)이다.

스케쥴러

여러 종류의 스케쥴링 알고리즘이 있고, 이 알고리즘들은 특정 우선순위를 기반으로 구현이 되는데 다음과 같다.

  1. CPU 최대 활용
  2. 처리량 최대화
  3. 대기 시간 최소화

이러한 우선순위를 목표로 다양한 알고리즘이 존재한다.

  • FCFS(First Come, First Serve) : 먼저 도착한 프로세스를 먼저 처리하는 스케쥴링, 선착순 알고리즘이다.
  • SJF(Shorted Job First) : 최단 작업을 우선하는 스케쥴링이다.
  • Priority Scheduling : 미리 주어진 프로세스의 우선 순위에 따라서 스케쥴링하는 방식이다.
  • RR(Round Robin) : 정해진 시간에 주어진 만큼 프로세스를 할당한 뒤 작업이 끝난 프로세스는 레디큐의 가장 마지막에 가서 재할당을 기다린다.
  • Multilevel-Queue : 레디큐를 여러개의 큐로 분류하여 각 큐가 각각 다른 스케쥴링 알고리즘을 가지는 방식이다.
  • Multilevel-Feedback-Queue : Multilevel-Queue는 특정 프로세스가 큐에 고정되어 있지만, Multilevel-Feedback-Queue는 큐와 큐 사이에 프로세스가 이동하는 것을 허용한다.

멀티 프로세스와 멀티 쓰레드

멀티 프로세스는 각자의 메모리 영역을 가지고 있어서 하나가 문제가 발생하더라도 서로가 독립적이라 안전성이 높은 장점이 있지만 그만큼 작업량이 많고 Context Switching이 많아지고, 성능저하가 일어날 것이다.

멀티 쓰레드는 Code, Data, Heap을 공유하고 있어 Context Switching 비용이 적고 성능이 좋다.
하지만 자원을 공유하고 있어 임계구역(Critical Section)에서 데이터를 동시에 변경하거나 변경되기 이전의 데이터를 다른 곳에서 사용하게 되는 동기화 문제가 생길 수 있다. 또 하나의 쓰레드에 문제가 생기면 부모 프로세스가 영향을 받아 모든 쓰레드가 영향을 받게 된다.


모바일 운영체제에서는 하나의 어플리케이션이 시작되면 하나의 프로세스와 하나의 기본 메인 쓰레드를 가지고 실행한다. 이어서는 안드로이드의 멀티 쓰레드에 대해서 알아보도록 하자.

모바일 운영체제에서의 쓰레드

안드로이드는 어플리케이션이 시작하면 하나의 프로세스가 생성되고 어플리케이션이 종료되면 프로세스는 소멸한다. 그리고 이 프로세서는 기본 메인 쓰레드로 시작을 하는데 이 메인 쓰레드는 앱이 실행중일 때 반드시 실행 중이어야 한다. 앱이 실행중일 때는 항상 사용자에게 화면이 보여져야하므로 메인 쓰레드를 UI 쓰레드라고도 한다.

프로세스는 반드시 하나 이상의 쓰레드를 갖고 있어야하고 그 하나는 무조건 메인 쓰레드가 포함되어 있어야 한다. 그만큼 UI 이벤트와 생명주기 메서드와 관련있는 메인 쓰레드는 문제없이 소중히 다뤄줘야 한다. 앱을 사용하다 보면 가끔씩 ANR(응답하지 않습니다.) 대화상자를 본 적이 있을 것이다. 이것이 메인 쓰레드가 몇초 이상 응답이 없어 생기는 크리티컬한 오류인 것이다. 이에 메인 쓰레드를 차단하지 않고 항상 유지하는 것이 매우 매우 중요하다!!

❗️그런데, 네트워크 통신 API를 사용하는 경우와 같이 대기 시간이 필요한 상황에서는 어떡해야 하죠..?

위와 같이 작업 수행은 해야하지만 즉각적인 반응이 보장되지 않는 작업들은 별도의 작업 쓰레드를 생성해서 실행하는 것이 올바르다. 즉 메인 쓰레드는 계속 유지되고 별도의 작업 쓰레드에서 작업을 하고 작업이 완료되면 소멸되는 방식인 것이다.

이처럼 모바일 운영체제에서는 쓰레드 관리가 중요하지만 그만큼 크리티컬하기 사용이 까다로운데 안드로이드 언어 kotlin 에서는 동시성 작업이 가능한 코루틴(Coroutine)이 존재한다.

코루틴(Coroutine)??
경량 쓰레드라고도 불리는 코루틴은 사실 쓰레드는 아니고 비슷한 기능을 하지만 각벼운 object로 쓰레드를 더 작게 쪼개서 사용하는 것이라고 생각하면 된다. 코루틴을 사용하면 특정 생명주기 안에서 비동기 스코프를 만들어 작성이 가능하다.
코루틴에 관해서는 이정도만 간략히 작성하고 새로 코루틴에 관한 글을 작성해야겠다.

profile
Android Developer

0개의 댓글