Concurrency Programming

Lena·2021년 3월 21일
2

Concurrency Programming

논리적으로 동시에 여러 일을 하는 것.
멀티스레딩 하는 것을 의미한다.
이에 비해 병렬성(Parallelism) 프로그래밍은 물리적으로(멀티 코어) 동시에 일을 하는 것을 말한다.

Multithread

하나의 프로세스(프로그램이 실행되어 메모리 위로 올라온 것)에는 하나 이상의 스레드가 존재한다(main thread).
thread는 코드 실행을 위한 하나의 흐름으로 생각하면 된다. thread를 하나 이상(main) 사용하는 것이 멀티스레딩이다.

Dispatch Queue

iOS는 멀티스레딩을 Queue로 관리하는데 serial, concurrent 2종류가 있다.

  • serial queue: 한 번에 하나의 클로저 실행 - main
  • concurrent queue: 여러 개의 스레드를 사용해서 동시 실행 - global

Queue(FIFO)를 기반으로 동작하기 때문에 항상 순차적으로 (큐에 먼저 추가된 것부터) task가 실행된다.

Sync, Async

큐에 closure를 추가할 때 두 가지 방법이 있다.

  • sync: 클로저가 종료될 때까지 current queue의 실행을 중지한다.(blocking)
  • async: current queue의 실행 흐름을 방해하지 않으면서 클로저를 실행한다.
DispatchQueue.main.async {
    // code
}

DispatchQueue.global().sync {
    // code
}

여기서 current queue는 dispatch main queue가 될 수도 있고 background queue가 될 수도 있다.

Current queue?
It may not be obvious what the source, or current, queue is, because it’s not always explicitly defined in the code. For example, if you call your sync statement inside viewDidLoad, your current queue will be the Main dispatch queue. If you call the same function inside a URLSession completion handler, your current queue will be a background queue.

DispatchQoS

main queue와 달리 global queue에 접근할 때는 DispatchQoS를 파라미터로 넘길 수 있는데,
DispatchQoS는 실행 우선 순위를 의미한다.

The quality of service, or the execution priority, to apply to tasks.

  • DispatchQoS.userInteractive : high priority, only do something short and quick
  • DispatchQoS.userInitiated : high priority, but might take a little bit of time
  • DispatchQoS.default : default quality-of-service class
  • DispatchQoS.utility : long-running background processes, low priority
  • DispatchQoS.background : not directly initiated by user, so can run as slow as needed

GCD, Dispatch

OS X, iOS는 개발자가 직접 스레드 관리하지 않고도 비동기식으로 작업을 수행할 수 있도록 기술(framework)을 제공한다. GCD는 앱의 스레드와 관련된 코드를 시스템 수준으로 이동시켜서, 필요한 만큼 스레드를 생성하고 작업을 스케줄링한다.
GCD는 iOS가 제공하는 멀티스레딩을 위한 Framework 이다.

Dispatch Queue는 GCD의 일부이다.
프로그래머가 실행할 task를 Dispatch Queue에 추가하면 GCD는 task에 맞는 스레드를 자동으로 생성해서 실행하고 작업이 종료되면 스레드를 제거한다.

Operation Queues

동시성 프로그래밍을 위해 Operation Queue를 사용하는 방법도 있다.
Dispatch Queue는 항상 FIFO로 작업을 실행하지만, Operation Queue는 작업의 실행 순서를 결정할 때 다른 요인을 고려한다.
이러한 요소 중 가장 중요한 것은 주어진 작업이 다른 작업의 완료 여부에 의존(depends on)하는지 여부이다.
task를 정의할 때, 종속성을 구성하고 이를 사용하여 task에 대한 복잡한 실행 순서 그래프를 만들 수 있다.
operation queue는 항상 동시(concurrent)에 operation을 실행하지만, 필요에 따라 종속성을 이용해 순차 실행하도록 할 수 있다.

let firstOperation = BlockOperation {
            for i in 1...10 {
                print("👻\(i)")
            }
        }
        
let secondOperation = BlockOperation {
           for i in 1...10 {
                print("💜\(i)")
            }
        }
        
let queue = OperationQueue()

// options

// 동시 작업할 operation 개수 지정
// 1로 설정할 경우 하나의 operation이 실행 및 완료된 이후 다음 operation이 실행된다.
queue.maxConcurrentOperationCount = 1

// 의존성 추가
// secondOperation이 끝나고 firstOperation을 수행
firstrOperation.addDependency(secondOperation)

// add queue
queue.addOperation(firstOperation)
queue.addOperation(secondOperation)

// 의존성을 추가한 경우 다음과 같이 출력된다.
💜1
💜2
💜3
💜4
💜5
💜6
💜7
💜8
💜9
💜10
👻1
👻2
👻3
👻4
👻5
👻6
👻7
👻8
👻9
👻10

Dispatch Queue vs. Operation Queue

  • Operation Queue에서는 동시에 실행할 수 있는 Operation의 최대 수를 지정할 수 있다.
  • Operation Queue에서는 KVO(Key Value Observing)을 사용할 수 있는 많은 프로퍼티들이 있다.
  • Operation Queue에서는 Operation을 일시 중지, 다시 시작 및 취소를 할 수 있다.
  • Operation Queue는 KVO를 사용해 작업 진행 상황을 감시해야 할 경우 적합하다.
  • Dispatch Queue는 작업이 복잡하지 않고 간단한 이벤트를 비동기적으로 처리할 때 적합하다.

Concurrency Programming
Operation
sync vs async
See also... Combine

0개의 댓글