TIL
🌱 난 오늘 무엇을 공부했을까?
📌 야곰닷넷 - Concurrency Programming 기초
📍 코어
- 코어는 CPU의 핵심으로 CPU에서 실제로 일을 처리한다.
- 한 번에 한 가지 일만 처리할 수 있다.
NOTE❗️
코어가 많더라도 작업의 분배과정에서 딜레이가 발생하거나, 소프트웨어 자체가 하나의 코어에 최적화 되어 있을 수 있으므로 하나의 코어를 가진 것 보다 무조건 빠르다고 할 수 없다.
📍 스레드
- 프로세스 내부에서의 가상의 작업 단위(논리적)이다.
📍 병렬(Parallel) 프로그래밍
- 여러 개의 CPU가 하나의 작업을 분담해서 처리하는 것이다.(동시)
- 물리적인 개념으로 CPU가 여러 개 있을 때에 가능하다.
📍 동시성(Concurrency) 프로그래밍
- 하나의 CPU가 여러 작업을 동시에 처리하는 것이다.
- 싱글 코어에서도 가능한 논리적인 개념이다.
- 여러 개의 스레드를 이용하여 동시에 여러 작업을 처리한다.
- 실제로는 번갈아가면서 작업을 처리하지만 아주 빠르게 Context Switching하기 때문에 동시에 작업을 처리하는 것처럼 보여진다.
📍 직렬성(Serial) 프로프래밍
- 동시성 프로그래밍과 반대되는 개념이다.
- 단 하나의 스레드에서만 작업을 하는 것이다.
- 동시에 작업을 처리하지 못하고, 순서대로 작업을 처리해야합니다.
📍 동기(Synchronous)
📍 비동기 (Asynchronous)
- 작업이 끝나는 것과 관계 없이 다음 작업을 진행한다.
동기와 비동기의 개념은 실행 종료 시점을 알 수 있는가에 대한 차이이다.
🔗 동시와 동기/비동기의 구분
- 동시성 :
Serial이냐, Concurrent인가는 스레드가 단일 스레드인가, 다중 스레드인가의 구분이다.
- 동기/비동기:
스레드의 수와는 무관하게 작업이 끝나기를 기다리냐, 기다리지 않느냐의 구분이다.
📍 동시성 프로그래밍 필요성
- 효율적으로 동작하는 소프트웨어
- 모든 일을 하나의 스레드에서 담당하지 않고 나눠서 작업처리한다.
- 사용성, 반응성이 좋은 소프트웨어
- 프로그램이 효율적으로 동작한다 -> 사용성, 반응성의 향상으로 이어진다.
🔗 동시성 프로그래밍 구현 방법
- GCD : 코드로서 동기/비동기 처리만 해준다면 시스템이 알아서 스레드를 관리해주는 방식
- Operationasync : Operation은 GCD를 기반으로 만들어졌으며 세부적인 기능들이 추가된 API
- async/await :
📌 GCD
📍 DispatchQueue
- 일련의 작업들을 DispatchQueue라는 대기열로 넘겨주면 시스템은 알아서 스레드를 관리하여 작업을 처리하도록 도와준다.
- FIFO(First In, First Out)로 작업을 처리한다.
- 단일 스레드 또는 다중 스레드 그리고 동기 작업 또는 비동기 작업 선택 필요하다.
🔗 Serial
- 단일 스레드에서 작업을 처리하는 것을 말한다.
- DispatchQueue를 초기화 할때 attributes의 Defualt 값이다.
🔗 Concurrent
📍 main / global
- main 스레드
- 앱의 기본이 되는 스레드이다.
- main스레드는 동시에 여러작업을 처리할 수 없다.(Serial Queue이기 때문에)
- 앱이 실행되는 동안 늘 메모리에 할당된다.
DispatchQueue.main
사용하며, 이것은 전역적으로 사용 가능한 큐이다.
- global 스레드와는 다르게 Run Loop가 자동으로 설정되고 실행된다.
- UI 작업은 메인 스레드에서만 작업할 수 있다.
- global 스레드
- 작업을 처리하기 위해 발생한 스레드
- global에 작업을 추가하면 새로운 스레드를 만들어 그 위에서 작업을 처리한다.
- 호출될때 메모리에 할당되며, 작업이 끝날시에 메모리에서 해제된다.
- global 메서드를 사용한다.
DispatchQueue.global()
-
sync와 async의 차이
- 다음 작업을 실행 하는데 있어 선행된 작업이 끝나기를 기다릴지 기다리지 않을지의 차이이다.
- 작업을 시키는 스레드의 주도권을 가져가는지 안가져가는지의 차이이다.
DispatchQueue.global().async {
DispatchQueue.global().sync {
for _ in 1...5 {
print("🥶🥶🥶🥶🥶")
sleep(2)
}
}
for _ in 1...5 {
print("😀😀😀😀😀")
sleep(1)
}
}
-
async와 concurrent
- async는 다음 작업을 실행 하는데 있어 선행된 작업이 끝나기를 기다리지 않고 작업을 진행하는 개념이다.
- concurrent는 하나의 작업을 여러개의 스래드를 사용하여 동시에 진행하는 개념이다.
-
DispatchQueue에서 serial 큐와 main 큐는 같을까?
- 같은 큐는 아니다.
- main 큐는 serial 방식으로 진행되는 큐이다.
-
DispatchQueue에서 main과 global()의 차이
- main 큐에서 main 스레드를 사용하는 방법은 main이다.
- global 큐에서 Background 스레드를 사용하는 방법은 global().
- main은 프로퍼티고, global()은 메서드이다.
- global()은 호출 될때마다 새로운 스레드를 생성하기 때문에 메서드.
-
main 스레드는 어떤 특징을 가지고 있나요?
- serial방식으로 진행되고 하나의 스레드(main 스레드)만 사용.
- UI 작업은 메인 스레드에서만 작업.
-
Serial에서 async의 동작
- async는 기다리지 않고 작업을 할당한 후, 다음 Serial 큐에 Dispatch 된 순서대로 동작한다.
-
serial 큐에서 sync로 작업을 처리하면?
- 큐에 들어가는 순서대로 작업을 실행하고, 작업이 완료된 후, 다음 작업을 실행한다.
- serial 큐에서 동일한 serial 큐를 부르면 데드락이 걸립니다.
import Foundation
let serial = DispatchQueue(label: "Serial")
serial.sync {
serial.sync {
for _ in 1...5 {
print("😀😀😀😀😀")
sleep(1)
}
}
}
-
main.sync
- deadlock에 빠진다.
- main은 sync의 작업이 끝나기를 기다리고, sync는 main의 작업이 끝나기를 기다리기 때문이다.
-
병렬 프로그래밍과 동시성 프로그래밍
- 병렬 프로그래밍: 실제로 동시에 여러 개의 코어가 처리하는 방법
- 동시성 프로그래밍 : 동시에 하는 것처럼 보이는 방법이다.
- 반대되는 개념이라기 보다 전혀 다른 개념으로 보는게 좋다.