논리적으로 동시에 여러 일을 하는 것.
멀티스레딩 하는 것을 의미한다.
이에 비해 병렬성(Parallelism) 프로그래밍은 물리적으로(멀티 코어) 동시에 일을 하는 것을 말한다.
하나의 프로세스(프로그램이 실행되어 메모리 위로 올라온 것)에는 하나 이상의 스레드가 존재한다(main thread).
thread는 코드 실행을 위한 하나의 흐름으로 생각하면 된다. thread를 하나 이상(main) 사용하는 것이 멀티스레딩이다.
iOS는 멀티스레딩을 Queue로 관리하는데 serial, concurrent 2종류가 있다.
main
global
Queue(FIFO)를 기반으로 동작하기 때문에 항상 순차적으로 (큐에 먼저 추가된 것부터) task가 실행된다.
큐에 closure를 추가할 때 두 가지 방법이 있다.
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.
main queue와 달리 global queue에 접근할 때는 DispatchQoS
를 파라미터로 넘길 수 있는데,
DispatchQoS는 실행 우선 순위를 의미한다.
The quality of service, or the execution priority, to apply to tasks.
OS X, iOS는 개발자가 직접 스레드 관리하지 않고도 비동기식으로 작업을 수행할 수 있도록 기술(framework)을 제공한다. GCD는 앱의 스레드와 관련된 코드를 시스템 수준으로 이동시켜서, 필요한 만큼 스레드를 생성하고 작업을 스케줄링한다.
GCD는 iOS가 제공하는 멀티스레딩을 위한 Framework 이다.
Dispatch Queue는 GCD의 일부이다.
프로그래머가 실행할 task를 Dispatch Queue에 추가하면 GCD는 task에 맞는 스레드를 자동으로 생성해서 실행하고 작업이 종료되면 스레드를 제거한다.
동시성 프로그래밍을 위해 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
Concurrency Programming
Operation
sync vs async
See also... Combine