[UMC] 7주차 - 스레드, 코루틴

Madeline👩🏻‍💻·2022년 11월 15일
0

kotlin study

목록 보기
11/19

0. 들어가기 전에..

  • 프로세스: 프로세서에 의해 동작하고 있는 프로그램

  • 스레드: 단위작업을 지원하기 위한 자원 할당의 단위

=> 자원은 프로세스 단위로 받고, 작업/스케줄링은 스레드 단위로 진행한다.

=> 스레드는 코드, 데이터, 파일을 공유함

🎈 스레드란?

1. 스레드

스레드는 한 프로세스 내에서 작동하는 실행 흐름 단위로,
프로세스에 속한 스레드들은 프로세스의 대부분의 영역(코드, 데이터, 힙 등)을 공유한다.
(공유하지 않는 것 = 스레드마다 독립적인 스택 영역을 갖는 것)

=> 스레드 간 문맥 교환이 발생할 때, 대부분의 영역은 공유를 하고 있는 상황이므로 문맥 교환의 비용이 낮다. 또 공유하고 있는 영역이므로 데이터를 주고받는 것도 매우 간단해진다.

Task: 할 일
Task를 표현하는 방법 -1) 프로세스(독립적인 메모리, 스택)
-2) 스레드(공유 메모리, 독립적인 스택)
OS가 스케줄러를 통해 Task를 표현하는 방법을 결정한다.
=> 대기하고 있는 task를 가져다가 cpu에 올려 실행하는 역할!

2. 코틀린에서의 스레드

JVM에서 10단계로 우선순위 설정을 제공하므로, 개발자가 우선순위를 설정할 수 있다. 멀티 스레딩 시, 우선 순위에 따라 OS의 스케줄링이 개입하여 작동한다. 따라서 스케줄링에 따른 문맥 교환(독립 스택 영역만 교환)이 존재한다.

=> 프로세스의 문맥 교환에 비해 비용이 상당히 적다.
=> 성능은 우수하지만 코드가 복잡해 개발자가 굉장히 꼼꼼하게 코딩해야 한다.

3. 스레드의 단점

1) 코드 작성이 복잡하다.

A 스레드의 결과 + B 스레드의 결과 => 결과 일 때,
A,B 스레드 작업의 완료 여부 및 결과를 공유자원 또는 콜백함수(Callback)를 만들어 해결해야 한다.
복잡하다..

2) 문맥 교환의 비용이 발생한다.

프로세스보다 비용이 적지만, 스레드 전환이 많거나 잦은 경우 최적화에 대한 고민이 필요하다.

이 단점을 보완하기 위해 등장한 것이 코루틴이다.

🎈 코루틴?

1. 코루틴 Coroutine

<안드로이드 공식 문서>

  • 경량: 코루틴을 실행 중인 스레드를 차단하지 않는 Suspension를 지원하므로 단일 스레드에서 많은 코루틴을 실행할 수 있습니다. Suspending은 많은 동시 작업을 지원하면서도 차단보다 메모리를 절약합니다.

  • 메모리 누수 감소: 구조화된 동시 실행을 사용하여 범위 내에서 작업을 실행합니다.

  • 기본으로 제공되는 취소 지원: 실행 중인 코루틴 계층 구조를 통해 자동으로 취소가 전달됩니다.

  • Jetpack 통합: 많은 Jetpack 라이브러리에 코루틴을 완전히 지원하는 확장 프로그램이 포함되어 있습니다. 일부 라이브러리는 구조화된 동시 실행에 사용할 수 있는 자체 코루틴 범위도 제공합니다.

    🎈 정리해보자!

하나의 작업(Job) = 루틴(routine),
루틴들이 멀티태스킹을 수행하는 것 = 코루틴

  • 코루틴은 스레드 내에서 작동하는 더 작은 꼬마 스레드!
  • 하나의 스레드에서 여러 개가 동작할 수 있다. (한 스레드에 수 천개의 코루틴 작동 가능)
  • 비용이 매우 적게 든다!
  • 동시성 프로그래밍을 위해 탄생하였다.
  • 논블로킹 작업들(루틴)을 정의한 뒤, 이것들을 조화롭게 활용하여 멀티태스킹을 수행하는 것을 말한다.

2. Dispatcher

자기가 관리하는 이미 초기화된 스레드 풀을 가지고 있는데,
이 중 쉬고 있는 스레드에 코루틴을 할당한 후 백그라운드에서 동작하도록 한다.

  • 이미 초기화된 스레드를 사용해서, 스레드 문맥 교환이 발생하지 않아 비용을 매우 줄일 수 있다.
  • 개발자가 설정가능한 일시 중단 가능한(Suspendable)함수에 의해 코루틴이 블로킹될 수 있다.
    • 넌블로킹/블로킹 제어 가능하다!
    • 이것이 스케줄링을 하기 위한 OS 개입을 줄여준다!

*넌블로킹?
Non-Blocking: 현재 작업을 수행중인 메인 스레드를 Blocking하지 않고, 백그라운드에서 작업을 수행하여 현재 스레드를 종료하지 않도록 하는 비동기적 작업 수행을 말한다.

3. 일시중단가능한 함수 Suspendable function

프로세스나 스레드는 일시 중단될 경우 막대한 문맥 교환의 비용이 든다.
Suspendable 함수는 특정 코루틴 내에서만 호출 가능하며, 이 함수는 자신을 호출한 코루틴을 중단할 수 있다.
메인 스레드에서는 호출할 수 없는 함수이다.

  • 기존 스레드에서는 콜백함수 / 공유 자원을 이용해야 했으나, 코루틴은 직관적으로 return된 값을 사용한다.

코루틴을 반환하므로 메인 스레드에 영향을 주지 않는다.
= 안전 함수!

4. 코루틴 라이브러리

코틀린은 간결한 코드로 사용 가능하도록 코루틴 라이브러리를 제공한다.
스레드를 이용할 때 콜백 지옥에 빠지지 않을 수 있도록 도와주고,
코드의 흐름도 직관적으로 잘 보인다.

🎈 실습해보아요

1. context switching

스레드 두 개를 만들어봅니다.

첫번째 스레드는 i가 0~1000, 두번째 스레드는 i가 1000~0까지
반복문을 돌면서 프린트됩니다.

Thread(){
            for(i in 0 until 1001){
                println(i)
            }
        }.start()

        Thread(){
            for(i in 1000 downTo 0){
                println(i)
            }
        }.start()

어떻게 출력되는지 Logcat을 열어보면,

12에서 갑자기 1000..

958에서 갑자기 13..
으로 바뀌는 걸 볼 수 있는데,
이를 컨텍스트 스위칭Context Switching이라고 한다.

문맥 교환(Context Switching)이란,
A 프로그램에서 B 프로그램으로 전환할 때,
A의 문맥을 저장하고, B의 문맥을 불러오는 것을 말한다.

이번에는 스레드 1에서 milk 변수를 1 씩 증가,
스레드 2에서 milk를 1씩 감소시키고, 0보다 작을 경우 hungry를 출력하게 해보자.

실행해보면

다음과 같다.
=> 컨텍스트 스위칭이 언제 일어나는 지 알 수 없다..라는 실습이었다

2. Handler를 사용해보자!

사진 4개를 drawale에 저장할건데, 사진은 R.java에서 int값으로 저장되기 때문에, arrayList를 Int 타입으로 설정한다.

메인 스레드를 제외한 다른 스레드에서는 view를 다룰 수 없다.(touch X)
=> Handler 사용
다른 스레드에서도 뷰를 다룰 수 있게!

영상을 올리기 넘 번거로워서 결과를 안올리지만,
1초마다 다음 화면으로 넘어간다!

참고:
https://full-stack.tistory.com/29

profile
Major interest in iOS 🍀 & 🍎

0개의 댓글