Haru's 개발 블로그

[운영체제] 3. Process - 2 (Thread) 본문

CS/운영체제

[운영체제] 3. Process - 2 (Thread)

Haru_29 2022. 6. 7. 20:08

 

Thread(lightweight process)

  • Thread란 프로세스의 내부의 CPU 실행 단위 / CPU 수행 단위이다.

동일한 작업을 하는 프로세스가 여러 개 인 경우 프로세스의 Address space는 하나만 생성하고 여러 개의 thread를 둠으로써 메모리의 낭비를 줄이고 프로세스마다 다른 부분의 코드를 실행할 수 있다. (lightweight process)

 

Thread의 구성

  • program counter
  • register set
  • stack space
  • thread가 동료 스레드와 공유하는 부분(=task)
    • code section
    • data section
    • OS resources
  • 전통적인 개념의 heavyweight process는 하나의 thread를 가지고 있는 task로 볼 수 있다.
  • 다중 thread로 구성된 태스크구조에서는 하나의 서버 thread가 blocked 상태인 동안에도 동일한 태스크 내의 다른 스레드가 실행(running)되어 빠른 처리를 할 수 있다. -> 자원절약 가능(메모리 낭비를 줄일수 있다)
  • 동일한 일을 수행하는 다중 thread가 협력하여 높은 처리율과 성능 향상을 얻을 수 있다.
  • thread를 사용하면 병렬성을 높일 수 있다.  이는 CPU가 여러개 달린 장치에서만 얻을 수 있는 장점이다. 왜냐하면 여러개의 thread에서 2개 이상의 CPU가 작동을 해야 병렬적으로 일을 할 수 있기 때문이다.

 

프로세스가 한개이기 때문에 PCB는 하나만 생성한다.

프로세스에 대한 정보를 담고있는 PCB를 보면 thread 끼리는

data, code 영역을 공유하되 stack은 별도로 할당받는다.

 

프로세스가 하나 주어지면 코드 데이터 스택으로 구성된 주소공간이 생성된다.

하나의 프로세스안의 여러개의 CPU수행단위를 스레드라고 한다
스레드는 프로세스 내에서 독자적으로 가져야할 정보만 가지고 있다.

Code, data가 공유하는 것을 확인가능, stack은 별도로 가지게 된다 (Binary는 무시하기)

 

 

Thread의 장점

 

1. Responsiveness(응답성)
다중 스레드로 구성된 태스크 구조에서는 하나의 서버 스레드가 blocked(waiting) 상태인 동안에도 동일한 태스크 내의 다른 스레스가 실행(running)되어 빠른 처리를 할 수 있다. 

예를들어 웹브라우저(프로그램)이 스레드를 여러 개 가지고 있다면 하나의 스레드가 이미지를 비롯한 추가 데이터를 받기 위해 서버에 요청을 걸어놓고 blocked 상태가 됐을 때 다른 스레드가 이미 받아놓은 HTML 텍스트를 우선적으로 화면에 출력할 수 있다. 이러한 일종의 비동기식 입출력을 통해 사용자의 답답함을 줄이고 응답성을 높일 수 있다.

 

2. Response Sharing
하나의 프로세스 안에 CPU 수행 단위(스레드)를 둬서 code, data, resource 자원을 공유함으로써 보다 효율적으로 자원을 활용할 수 있다.

 

3. Economy

  • 새로운 프로세스 하나를 만드는 것 보다 기존의 프로세스에 스레드를 추가하는 것이 overhead가 훨씬 적다.
  • CPU switch 역시 프로세스 단위로 교환이 일어나는 것 보다 프로세스 안에서 스레드 끼리 교환이 일어나는게 overhead가 적다.
  • Solaris(Unix)의 경우 위 두 가지 overhead가 각각 30배, 5배

4. Utilization of MP Arcitectures (CPU가 여러개 일때 얻을수있는 장점)
각 스레드가 서로다른 CPU에서 병렬적으로 일을 할 수 있다.
그래서 결과를 빠르게 얻을수있다.

 

Thread의 실행

 

스레드는 실행 방법에 따라 다음의 두 가지 타입으로 나눌 수 있다.

  • Kernel Thread ─ 운영체제가 스레드가 여러 개인 것을 알고 있어서 스레드간의 CPU 교환을 커널이 CPU 스케줄링을 하듯이 관리한다.
    • Windows 95/98/NX
    • Solaris
    • Didital UNIX,Mach
  • User Thread ─ 운영체제는 스레드가 여러 개인 것을 모르는 상태에서 사용자 프로그램이 라이브러리의 지원을 받아 스스로 여러 개의 스레드들을 관리한다. 커널이 스레드의 존재를 모르기 때문에 구현에 제약이 있을 수 있다.
    • POSIX Pthreads
    • Mach C-threads
    • Solaris threads

(그밖에 real-time 스레드들도 존재한다.)

 

 

 

 

iOS에서의 Thread

 

iOS에서 Thread는 두 가지 종류가 있다

  • Main Thread
  • Global Thread (=Background Thread)

1. Main Thread

  • Main Thread는 하나만 존재 한다.(그외는 전부 Global Thread)
  • 우리가 일반적으로 작성하는 코드는 대부분은 MainThread에서 작성이 됩니다. 일반적으로 이 사실을 인식하지 못 하는 이유는 우리가 작성된 코드는 Cocoa에서 실행되는데 Cocoa가 코드를 main Thread에서 호출하기 때문이다.
  • UI적인 요소는 전부 Main Thread에서 다루게 된다.
    • UIKit의 모든 속성을 Thread-safe하게 설계하면, 느려짐과 같은 성능저하가 발생할 수 있기 때문에 그렇게 설계할 수 없다. (Thread-safe하지 않게 설계한 것은 애플의 의도다.)
    • 메인 런루프(Runloop)가 뷰의 업데이트를 관리하는 View Drawing Cycle을 통해 뷰를 동시에 업데이트 하는 그런 설계를 통해 동작하고 있는데, (메인쓰레드가 아닌)백그라운드 쓰레드가 각자의 런루프로 그런 동작을 하게되었을때, 뷰가 제멋대로 동작할 수있다. (예를  들어, 기기를 회전 했을때, 동시에 뷰의 레이아웃이 재배치되는 그런 동작을 못하게 될 수도 있다.)
    •  iOS가 그림의 그리는 렌더링 프로세스(코어애니메이션 -> 렌더서버 -> GPU -> 표시)가 있는데, 여러 쓰레드에서 각자의 뷰의 변경사항 GPU로 보내면 GPU는 각각의 정보를 다 해석해야하니 느려지거나, 비효율적이 될 수 있다.
    • Texture나 ComponentKit이라는 페이스북에서 개발한 비동기적 UI 프레임워크가 있긴 하지만, View Drawing Cycle가 유사한 방식으로 적절한 타이밍에 메인 쓰레드에서 동시에 업데이트 하도록 하고 있다.
  • 만약 UI적인 작업을 background에서 작업하는 경우 Main Thread Cheaker에서 보라색으로 경고창이 뜨게된다.

  • Main Thread는 Main Queue에서 실행이 되는데 Main Queue가 Serial Queue라서 한개에 하나의 Task밖에 실행을 못함

 

2. Background Thread

  • iOS의 framework들은 background에서 구동이 된다. -> 만약 Main Thread에서 구동되면 앱이 멈출 것이다.
  • 몸체는 Background에 있지만 가끔 필요할 때 Main Thread에게 손(Delegate)을 뻗는 구조이다.
  • 예를 들면 어플 에서 음악을 재생 -> 음악 재생에 필요한 Framework를 사용 -> 이떄 음악 재생에 필요한 Framework는 모두 background에서 실행, 가끔 음악 재생의 성공을 알려 줄 때는 Delegate,Completion handler 등을 통해 Main Thread에게 알려 통제를 한다.
  • Core Animation의 작업은 background에서 실행이 된다. 만약, animation이 동작을 하게되고 user interaction이 막힌다면 animation을 쓸 수 없다. 따라서 layer를 업데이트 시키는 animation 동작은 backgorund thread에서 실행 -> delegate method와 completion handler를 이용하여 main thread에서 animation을 컨트롤 가능하다.

3. Background Thread 사용할 때 주의해야 할 점

  • 원래는 code는 한 줄 씩 실행이 되는데 background thread가 개입을 하게 되면 이 원리가 깨지게 됩니다. 이 말은 작업이 완료되는 순서를 예상할 수 없게 됩니다.
  • main thread와 background thread는 병렬적(Concurrent)으로 작업을 수행한다. 따라서 main thread에서 실행이 되고 있는 code 사이에 background thread에서 실행된 code가 어떤 식으로 개입이 될지 알수가 없어진다.
  • 그리고 thread를 고려하면서 code를 구현하는 것은 어렵지만 test와 debug하는 것도 어렵다.

4.xcode에서 제공해주는 thread 관리 tool

  • Debug navigator: thread를 구분하여 대기중인 call이 enqueue되는 시점을 알려준다.
  • Time Profiler: 다른 thread의 활동을 기록해준다.
  • Thread Sanitizer: 발생할 수 있는 문제를 감지한다.
  • NSLog와 os_Log: 우측 하단 console창에 호줄된 thread를 식별 하는 번호를 print한다.

 

Sync and Async / Serial and Concurrent

 

1. Sync and Async

  Synchronous Asynchronous
정의 요청에 대한 응답이 동시에 이루어져야 한다
모든 작업을 순차적으로 진행한다
요청에 대한 결과가 동시에 일어나지 않는다
모든 작업을 동시에 진행한다
장점 설계가 매우 간단하고 직관적이다. 응답이 주어질 때까지 기다리지 않고
다른 작업을 하므로 자원을 효율적으로 사용할 수 있다
단점 응답이 주어질 때까지 아무 것도 못하고 대기해야 한다 동기보다 설계가 복잡하다

 

2. Serial and Concurrent

  • Serial 
    • 내 Queue에 들어온 작업들을 순차적으로 실행시킨다.
    • Serial Queue는 한 번에 하나의 task만 실행시킨다.

  • Concurrent
    • 내 Queue에 들어온 작업들은 동시다발적으로 실행 시킨다.
    • Concurrent Queue는 한 번에 여러 개의 Task를 실행시킬 수 있다.

Sync and Async / Serial and Concurrent 조합

 

 

각 cell에서 이미지를 로드 할 때, 어떤 데이터가 먼저 들어 올지 중요하지 않다. 그냥 빠르면 좋다. -> Concurrent Queue

반대로 순서가 중요한 작업들을 처리를 해야 한다. -> Serial Queue

  • SerialQueue.aync : 메인 스레드의 작업 흐름이 queue에 넘긴 task가 끝날 때까지 멈춰있고(sync), 넘겨진 task는 queue에 먼저 담겨있는 작업들과 같은 Thread에 보내지고 해당 작업들이 모두 끝나야 실행(Serial Queue)
  • ConcurrentQueue.aync :  메인 스레드의 작업 흐름이 queue에 넘긴 task가 끝날 때까지 멈춰있고(sync), 넘겨진 task는 queue에 먼저 담겨있는 작업들과 다른 Thread에 보낼 수도 있기 떄문에 해당 작업들이 모두 끝나지 않아도 실행(Concurrent Queue)
  • SerialQueue.async : 메인 스레드의 작업 흐름이 queue에 넘기자마자 반환되고(async), 넘겨진 task는 queue에 먼저 담겨있는 작업들과 같은 Thread에 보내지고 해당 작업들이 모두 끝나야 실행(Serial Queue)
  • ConcurrentQueue.async : 메인 스레드의 작업 흐름이 queue에 넘기자마자 반환되고(async), 넘겨진 task는 queue에 먼저 담겨있는 작업들과 다른 Thread에 보낼 수도 있기 떄문에 해당 작업들이 모두 끝나지 않아도 실행(Concurrent Queue)

 

 

 

 

GCD(Grand Central Dispatch)

 

GCD란?

애플은 쉽고 편한 Multi Threading을 위하여 API를 제공해 주는데 GCD는 C언어 기반이라서 가볍고 성능면에서 뛰어나다. 그리고 Closure로 구현이 되어 있어 코드 가독성도 좋고 간단하게 사용이 가능하다. 단, 작업 취소,KVO,재사용 등은 직접 만들어 줘야 한다.

 

 

이러한 작업이 있으면 메인 스레드 뿐만이 아니라 다른 스레드로 분산 처리를 하면 효율적 일것 입니다.

그러면 이때 GCD는 Queue에다가 task를 보낸다음 알아서 분배를 해주게 됩니다.

 

GCD는 Dispatch Queue를 사용해서 Multi Threading을 지원한다.

 

Dispatch Queue의 종류

 

  • Serial Queue
    • Task들을 순차적으로 처리하며, 한번에 한 개의 Task밖에 처리 못 한다.

 

 

 

 

  • Concurrent Queue
    • 동시에 여러 개의 Task들을 처리한다.
  • Main Queue(Serial Queue)
    • Main Thread에서 사용되는 Queue이며 Serial Queue이고 UI 관련 작업은 여기서 진행이 되어야한다.
    • Main Queue에는 절대로 Sync Task를 추가 할 수가 없다.
DispatchQueue.main.async {
    //원하는 작업
}
  • Global Queue(Concurrent Queue)
    • Global Queue는 편의상 사용할 수 있게 만든 Concurrent Queue이며 정의에는 Qos를 제공한다.
    • Qos란 Priority(우선 순위)인데 우리가 직접 우선 순위를 입력 할수가 있다.
    • Qos를 잘 활용하면 에너지 효율성이 좋아진다.
DispatchQueue.global().sync {
    //원하는 작업
}
DispatchQueue.global().async {
    //원하는 작업
}
userInteractive 중요도가 높고 즉각적인 반응이 요구되는 작업(UI업데이트, 이벤트핸들링 등)일 때 사용
사용자의 행동에 즉각적인 반응을 기대하지만 이를 메인 스레드에서 전부 처리하면 많은 로드가 걸리는 작업들을 userInteractive에서 처리하여 동작하는 것처럼 보인다.
Main Thread에서 실행되는 Qos
즉각적으로 실행
userInitiated userInteractive까진 아니더라도 유저가 빠른 결과를 기대할 때 사용
저장된 파일을 열거나 할 때 사용한다.
몇 초 이하나 거의 즉각적
default 작업을 분리하지 않을 때 사용되는 Qos로 기본값이다.  
utility 즉각적인 결과가 필요하지 않을 때
프로그레스 바가 등장하는 작업에 어울린다.
(네트워크, 다운로드, 계산, 데이터를 가져오기 등을 처리 등)
몇 초 ~ 몇 분
background 급히 필요하지 않은 작업일 때
사용자에겐 보이지 않는 처리 (ex: 백업)
background로 줄 경우 iPhone 저전력 모드에선 실행되지 않는다
몇 분 ~ 몇 시간
unspecified Qos 정보가 없음을 나타냄
시스템에게 Qos를 추론하라는 신호를 준다.
거의 사용할 일은 없다.

 

 

  • Custom Queue
    • 커스텀으로 만든다.
    • default로 Serial 특성을 가진다. 하지만 Concurrent로 설정이 가능하다.
    • Qos 설정 가능하다.

이렇게 생성 할때 인자에 label을 붙이면 custom queue가 된다. 그리고 default값인 Serial 특성을 가지게 된다.

let customSerialQueue = DispatchQueue(label : "yoon")

그리고 Concurrent으로도 설정이 가능하다.

let customConcurretnQueue = DispatchQueue(label: "yoon", attributes: .concurrent)

qos를 따로 설정을 하지 않았기 떄문에 OS에서 알라서 추론을 하지만 설정도 가능하다.

let customConcurrentQueue = DispatchQueue(label: "yoon", qos: .background, attributes: .concurrent)

 

 

  • GCD 주의사항
    • UI관련 작업은 모두 Main Queue에서만 담당한다.
      • 다른 Queue에서 작업하다가도, 화면에 표시해야 하는 작업은 반드시 MainQueue로 보내서 작업해야한다.
    • 플레이그라운드에서는 mainQueue를 사용하지 않는다.
    • 메인 큐에서 다른 큐로 보낼 때 sync를 사용하면 안된다.
      • 다른 스레드에서 작업 하는 이유는 메인에서 동작하는 작업과 동시적으로 수행하여 속도를 향상시키기 위해서 이다.
      • sync를 사용하면 해당 작업이 끝날때까지 메인 스레드를 block 시키기 때문에 앱이 버벅거린다.
    • 현재 큐에서 같은 큐로 sync를 사용하면 안된다.
      • 실행되고 있던 스레드에서 해당 큐로 sync로 작업을 보내면 실행중이던 스레드는 block 상태가 된다.
      • 다시 현재 큐에 들어온 작업을 스레드에 배치하는 과정에서 block 상태의 스레드에 배치된다면 교착상태가 발생한다.
    • 작업을 보낸다는 것은 클로저를 보낸다는 것이므로 캡처 현상이 발생한다. 
      • 객체 내부에서 비동기 globalQueue를 사용하는 경우 weak self 선언해주지 않으면 strong 참조를 하게 되어서 작업 도중 객체가 사라지게 되어도 ARC가 남아 있어서 여전히 동작을 하게 된다.(strong capture현상)
      • 따라서 weak 선언을 통해 객체가 사라질 때 작업도 자연스럽게 종료가 되어야한다.
      • 캡처 현상이란 클로저를 변수에 할당하거나 클로저를 호출하는 순간 클로저는 지속적으로 외부 변수를 사용하기 때문에 자신이 참조하는 외부의 변수를 참조한다.
var stored = 0

let closure = { (number: Int) -> Int in
    stored += number
    return stored
}

closure(3) // 3

closure(4)   // 7

closure(5) // 12

stored = 0

closure(5)   //  5

위의 코드에는 클로저에서 stored 변수를 사용하기 때문에 힙에 저장되는 클로저에 stored 변수 주소를 캡처한다.

 

 

 

 

멀티 스레드(Multi Thread)사용 할때 고려해야 할점

 

멀티 스레드란?

  • 여러 개의 스레드가 동시에 진행되는 것을 의미한다.
  • 하나의 프로세스 내에서 여러 개의 스레드가 존재하고, 스레드들은 프로세스의 자원은 공유하되 실행은 독립적으로 이뤄지는 구조이다.

멀티 스레드의 장점

  • 메모리 공간과 시스템 자원 소모가 줄어든다.
  • 프로세스의 통신 방법에 비해 스레드의 통신 방법은 간단하다. -> 별도의 자원을 이용하는 것이 아니라  전역 변수의 공간 또는 동적으로 할당된 공간인 Heap 영역을 이용하여 데이터를 주고 받기 때문이다.

멀티 스레드의 단점

  • 서로 다른 스레드가 데이터와 Heap영역을 공유하고 있기 때문에 어떤 스레드가 다른 스레드에서 사용 중인 변수나 자료구조에 접근하여 이상한 값을 읽어올 수 있다. -> 멀티 프로세스는 프로세스간 공유하는 자원이 없기 때문에 동일한 자원에서 동시에 접근하는 경우가 없다.
    • 병목현상이 발생하여 성능이 저하될수가 있다. -> 과도한 락(lock)으로 인한 병목현상을 줄여줄수가 있다.

멀티스레드 프로그래밍에서 고려해야 할점

 

  • UI업데이트 작업은 메인 스레드에서 구현이 되어야 한다.
  • 스레드에 안전하지 않은(Thread-unsafe)변수는 서로 다른 스레드에서 접근하면 위험하기 때문에 신경써서 작업을 해야한다.

1. Mutable(변경이 가능한), Immutable(변경이 불가능한)

  • Immuable한 인스턴스는 스레드에 안전(Thread-safe)한다. 따라서 여러 스레드에서 한번에 접근해도 문제 없다.
  • Mutable한 인스턴스는 스레드에 안전(Thread-safe)하지 않지만 읽기 전용으로 사용하면 문제는 없다.
  • 단, Mutable한 인스턴스를 하나 이상의 스레드에서 변경이 이루어진다면 문제가 발생한다.

2. 프로퍼티 속성

 

 atomic

  • 데이터의 변경이 한 번에 일어난 것처럼 보이게 하는 것이다.
  • 데이터의 값을 변경하는 작업에는 항상 값 변경의 시간이 필요하다.
  • 멀티쓰레드 환경에서 데이터의 무결성이 보장되어야 할 때 사용.(안정성 +, 처리속도 -)
  • ObjectiveC에서 사용한다.
  • 데이터가 반드시 변경 전, 변경 후의 상황에만 보장을 한다.
  • 따라서, 데이터의 변경 중에는 해당 데이터에 접근을 할수가 없다.

nonatomic

  • 데이터의 무결성을 보장 받지 않아도 될때 사용 (안정성 -, 처리속도 +)
  • 예를 들어, atomic으로 설정된 property의 getter/setter 메소드는 lock을 사용하여 멀티스레드를 안전하게 처리하는데, 이 광정에서는 다른 스레드가 접근을 할수가 없기 때문에 불필요한 성능저하가 발생한다.
  • 기본적으로 Swift는 Thread-Safe를 고려한 언어는 아니기 때문에 모든 non-atomic이다. 그리고 별도로 atomic을 지정할수가 없다.
  • 그래서 Swift를 atomic으로 정의하기 위해선 GCD를 통해 구현해준다.

 

class AtomicValue<T> {
    let queue = DispatchQueue(label: "queue")

    private(set) var storedValue: T

    init(_ storedValue: T) {
        self.storedValue = storedValue
    }

    var value: T {
        get {
            return queue.sync {
                self.storedValue
            }
        }
        set { // read, write 접근 자체는 atomic하지만,
              // 다른 쓰레드에서 데이터 변경 도중(read, write 사이)에 접근이 가능하여, 완벽한 atomic이 아닙니다.
            queue.sync {
                self.storedValue = newValue
            }
        }
    }

    // 올바른 방법
    func mutate(_ transform: (inout T) -> ()) {
        queue.sync {
            transform(&self.storedValue)
        }
    }
}

let atomicInComplete = AtomicValue<Int>(0)
let atomicComplete = AtomicValue<Int>(0)
DispatchQueue.concurrentPerform(iterations: 100) { (idx) in

    atomicInComplete.value += idx

    atomicComplete.mutate { $0 += idx }
}

print(atomicInComplete.storedValue) // 결과: 돌릴 때마다 다름
print(atomicComplete.storedValue) // 결과: 4950

프로퍼티 속성에는 atomic,nonatomic이 있다.

어떤 프로퍼티를 두 개의 스레드가 참고하고 있는 상황에서 해당 프로퍼티 접근자 메서드가 atomic하지 않는다면 값에 대한 싱크가 맞지 않아 문제가 발생할 수 있다. 이런 경우에 atomic으로 설정되어야 한다.

단, Mutable한 인스턴스가 변경 중에 동시 접근 할 수가  nonatomic으로 해도 상관없다.

 

3.Sychronized

메소드를 실행할 때 동시에 접근할 수가 없도록 막아 주고 싶을 때 lock을 걸어 준다.

Lock을 걸어줌으로써 한 스레드에서 해당 부분이 끝날 때 까지 다른 스레드에서 접근할 수 없게한다.

 

4.GCD

Swift에서 스레드 관련 작업은 Grand Central Dispatch API를 통해 처리를 한다.

GCD는 클로저 블록 안에 있는 특정 작업을 큐에 올리고, 해당 큐를 특정 스레드에 실행하는 방식이다.

 

5. Class, Struct

클래스는 레퍼런스 타입, 구조체는 값 타입이다. 따라서, 구조체가 파라미터로 전달될 때 스레드가 안전(Thread-safe)하다.

 

마지막으로 멀티 스레드를 사용하여 개발 할 때에는 스레드에 안정하지 않은 (Thread-unsafe) 변수를 사용한다면 변경 중에 동시에 접근하는 경우가 있는지 잘 체크해야한다.

 

런 루프(RunLoop)

 

Global Thread에서는 Timer가 작동되지 않는다.

 

Main Thread

 

Global Thread

 

 

RunLoop란?

  • RunLoop는 입력 소스를 처리하는 이벤트 처리 루프이고, Timer 또한 같이 처리한다.
  • Thread의 외부 입력 소스 및 Timer를 처리 할 때 사용
  • Thread는 모두 각자의 RunLoop를 가질 수 있다.
  • Thread를 생성 할 때 RunLoop가 자동으로 생성이 된다.
  • 단, RunLoop는 자동으로는 실행되지 않는다.
  • 따라서, 만약 내가 Thread를 생성 했는데, 이 Thread가 입력 소스나 Timer를 처리해야 한다면, 직접 RunLoop를 얻어서 실행을 해야한다.
class var current: RunLoop { get }

현재 실행 중인 스레드 내에서 다음과 같이 작성하게 된다면

let runLoop = RunLoop.current

현재 Thread에 대한 RunLoop를 얻을 수 있다. 다만, RunLoop를 얻는 것만으로는, 입력 소스 및 타이머를 처리해 주지 않는다.

따라서 run을 통해서 RunLoop를 직접 실행시켜주어야 한다.

 

RunLoop는 루프를 수행 할 때 2가지 Event Source를 수신한다.

  • Input Source : 다른 스레드나 Application으로부터 온 비동기 이벤트를 처리한다.
  • Timer: 예약 된 시간 또는 반복 간격으로 발생하는 동기 이벤트를 전달한다.

노란 색 루프 한바퀴 도는 작업이 한 번의 실행이라 생각하면 RunLoop는 한 번의 실행 동안 내 스레드에 도착한 이벤트를 받고 ->

이에 대한 핸들러를 수행하는 객체이다.

다만, RunLoop는 내부적으로 반복 실행하지는 않는다. -> 한 번 Event Source를 읽고 전달하는 실행이 끝나면 그대로 대기한다.

따라서, 스레드 내에서 명시적으로 for,while 등을 이용해 RunLoop를 반복 실행시켜 준다.

 

RunLoop를 실행시키는 방법

앞에서 Global Thread를 손수 생성하고 -> Global Thread의 RunLoop는 실행되지 않는다. -> 따라서 Timer를 작동 시켰지만 내 Thread의 RunLoop가 이 Event를 처리하지 못해서 실행되지 않는다.

Main Thread의 경우 -> Main Thread는 Application이 실행될 때 프레임워크 차원에서 자동으로 RunLoop를 설정하고 실행한다.

 

 

 

 

 

참고 사이트

https://babbab2.tistory.com/65?category=831129 

 

iOS) GCD (Grand Central Dispatch)

안녕하세요 :) 소들입니다.. 오늘은 iOS의 이 쓰레드란 놈에 대해 마무리를 지어볼까 해요.. 아마 이번에 GCD좀 다루면 대강 끝나지 않을까 싶네요 :) 먼저 iOS의 Main Thread / Global Thread 에 대해서 이해

babbab2.tistory.com

https://sujinnaljin.medium.com/ios-%EC%B0%A8%EA%B7%BC%EC%B0%A8%EA%B7%BC-%EC%8B%9C%EC%9E%91%ED%95%98%EB%8A%94-gcd-2-a65e1c28665d

 

[iOS] 차근차근 시작하는 GCD — 2

GCD와 Operation에 대해 알아봅시다

sujinnaljin.medium.com

https://hcn1519.github.io/articles/2019-03/atomic

 

atomic/non atomic

atomic의 개념에 대해서 알아봅니다.

hcn1519.github.io

https://gwangyonglee.tistory.com/m/47

 

[iOS] 멀티 스레드(Multi Thread) 구현 시 고려해야될 것들

안녕하세요. iOS앱을 개발하면서 멀티 스레드로 앱을 구현하다보면 예상하지도 못한 곳에서 죽는 경우를 경험해보셨을 것입니다. 그래서 이번 글에서는 멀티 스레드를 구현하면서 고려해야될

gwangyonglee.tistory.com

 

 

 

 

 

 

 

 

 

'CS > 운영체제' 카테고리의 다른 글

[운영체제] 3. Process - 1  (0) 2022.05.29
[운영체제] 1. 운영체제란?  (0) 2022.05.29
[운영체제] System Call  (0) 2022.05.24
[운영체제] 인터럽트(Interrupt)  (0) 2022.05.24
[운영체제] 프로세스의 주소 공간  (0) 2022.05.24
Comments