Serial - Concuurency 와 Async-Sync는 얼핏 보면 비슷한 작동원리 같다.
하지만 다르다. 하나씩 뜯어보자.
Async - Sync
Async 와 Sync는 작업 입장에서 요청과 응답의 관점이다.
응답 = return
난 이 일이 요청 즉시 응답을 줬으면 좋겠어 -> Sync
난 이 일이 요청은 하지만 응답은 천천히 줘도 돼 -> Async
Serial - Concurrency
Serial 과 Concurrency의 관계는 큐의 입장에서 일을 처리 하는 과정이다.
Serial
- 일을 순차적으로 한다. (일의 끝을 보고 다음 일을 한다.)
Concurrency
- 일을 동시 다발적으로 한다.
1번 코드 블럭
let concurrentQueue = DispatchQueue.init(label: "Concurrency", attributes: .concurrent)
concurrentQueue.sync { print("start") } // 1️⃣번 작업
concurrentQueue.async { for _ in 0...5 { print("async") }} // 2️⃣번 작업
concurrentQueue.sync { for _ in 0...5 { print("sync") } } // 3️⃣번 작업
concurrentQueue.sync { print("end") } // 4️⃣번 작업
1번 코드 블럭은 Disaptchqueue가 concurrent로 작업한다.
1️⃣번 작업이 등록된다.
sync
로 등록 -> 바로 출력한다.1️⃣번 작업이 끝난 후에 2️⃣번 작업이 등록된다.
async
로 등록- 출력을 시작한다. 하지만 concurrent 이므로 다음 작업으로 넘어간다.
3️⃣번 작업이 등록된다.
sync
로 등록 -> 바로 출력한다.But. 2️⃣작업이 이미 실행중이다. concurrent 하므로 2️⃣, 3️⃣ 동시에 작업된다.
하지만 2️⃣작업이 끝날 때 까지 4️⃣은 시작하지 않는다.
2️⃣작업이 끝난 후에 4️⃣작업이 시작된다.
2번 코드 블럭
let serialQueue = DispatchQueue.init(label: "Serial")
serialQueue.sync { print("start") } // 1️⃣번 작업
serialQueue.async { for _ in 0...5 { print("async") }} // 2️⃣번 작업
serialQueue.sync { for _ in 0...5 { print("sync") } } // 3️⃣번 작업
serialQueue.sync { print("end") } // 4️⃣번 작업
비슷하지만 살짝 다르다. 1번은 Concurrency 하게 작동하고 2번은 Serial로 동작한다.
* DispatchQueue의 default는 Serial 하게 작동한다.
1️⃣번 작업이
sync
로 등록된다.1️⃣번 작업이 끝난 후에 2️⃣번 작업이 시작된다.
- async로 등록되었지만 DispatchQueue가 Serial 하다. 즉 작업이 끝날 때 까지 다음 작업은 실행하지 않는다.
* 작업이 실행하지 않는다 였다. 코드가 실행 안되는건 아니다.
- async로 등록되었지만 DispatchQueue가 Serial 하다. 즉 작업이 끝날 때 까지 다음 작업은 실행하지 않는다.
3️⃣번
sync
로 작업이 등록된다. 만약 2️⃣번 작업이 안 끝났다면 3️⃣번 작업은 기다린다.3️⃣번 작업이 끝나면 4️⃣번 작업이 실행된다.
살짝 미묘하게 다름을 인지했음 좋겠다.
문제를 통해서 다시 한 번 살펴보자.
let concurrentQueue = DispatchQueue.init(label: "Concurrency", attributes: .concurrent)
concurrentQueue.sync { print("start") } // 1️⃣번 작업
concurrentQueue.async { for _ in 0...5 { print("async") }} // 2️⃣번 작업
concurrentQueue.sync { for _ in 0...5 { print("sync") } } // 3️⃣번 작업
print("💙")
concurrentQueue.sync { print("end") } // 4️⃣번 작업
Quiz) 💙보다 sync
가 먼저 출력 될 수 있을까? ❌
3️⃣번 작업이 등록 된 후 DispatchQueue가 concurrent 하더라도 3️⃣번 작업이 안비켜 주고 있는 것이다.
그러므로 3️⃣번 작업이 다 끝나야 💙가 출력될 수 있다.
Quiz) 💙보다 async
가 늦게 될 수 있을까? ✅
2️⃣번 작업은 이미 등록이 되어 async
하게 작업되고 있다. 그렇기에 💙출력과 관계 없이 작업이 진행된다. 그렇기에 async
출력이 늦을 수 있다.
let serialQueue = DispatchQueue.init(label: "Serial")
serialQueue.sync { print("start") } // 1️⃣번 작업
serialQueue.async { for _ in 0...5 { print("async") }} // 2️⃣번 작업
serialQueue.sync { for _ in 0...5 { print("sync") } } // 3️⃣번 작업
print("💙")
serialQueue.sync { print("end") } // 4️⃣번 작업
Quiz) 💙보다 async
가 늦게 될 수 있을까? ❌
2️⃣번 작업이 async로 등록되었다.
DispatchQueue가 serial 하므로 3️⃣번 작업이 요청 되었다 하더라도 2️⃣이 끝나기 전까지 시작하지 못한다.
3️⃣번이 끝나지 않으면 💙도 출력될 수 없다
그러므로 💙보다 async
가 늦게 될 수 없다.