Jupyo's Daily Story
스레드 (Thread) 본문
스레드(Thread)란?
스레드는 하나의 프로세스 내에서 실행되는 최소 실행 단위입니다. 프로세스는 독립적으로 실행되는 프로그램을 의미하는데, 프로세스 내부에서 여러 작업을 동시에 처리할 때 사용하는 것이 스레드입니다. 스레드는 프로세스의 자원을 공유하며, 멀티태스킹을 구현할 수 있는 기본적인 단위로 사용됩니다.
프로세스와 스레드의 차이
- 프로세스(Process): 운영체제에서 실행 중인 프로그램을 말하며, 독립된 메모리 공간을 가지고 있습니다. 하나의 프로세스는 여러 스레드를 가질 수 있습니다.
- 스레드(Thread): 프로세스 내에서 독립적으로 실행되는 흐름입니다. 스레드는 같은 프로세스의 메모리와 자원을 공유하면서 작업을 병렬로 처리합니다.
주요 차이점
- 프로세스는 각각 고유한 메모리 공간을 사용하여 다른 프로세스와 자원을 공유하지 않음.
- 스레드는 같은 프로세스 내에서 실행되며, 서로 메모리와 자원을 공유함.
멀티스레딩(Multithreading)
멀티스레딩은 하나의 프로세스가 여러 스레드를 사용하여 동시에 여러 작업을 수행하는 방식입니다. 멀티스레드를 사용하면 CPU 자원을 효율적으로 활용하고 프로그램의 성능을 크게 향상 시킬 수 있습니다.
스레드의 상태(Thread States)
스레드는 실행되는 동안 여러 상태를 거칩니다. 스레드의 상태는 운영체제에 의해 관리됩니다.
- 생성 상태(New): 스레드가 생성되고 아직 실행되지 않은 상태.
- 준비 상태(Runnable): 실행 준비가 완료된 상태지만, CPU를 할당받지 못해 실행 대기 중인 상태.
- 실행 상태(Running): CPU에서 실행되고 있는 상태.
- 대기 상태(Waiting): 스레드가 잠시 중단되어 어떤 조건이 충족될 때까지 대기 중인 상태.
- 종료 상태(Terminated): 스레드의 작업이 모두 완료되어 종료된 상태.
스레드의 장점
병렬 처리(Concurrency)
스레드는 동시에 여러 작업을 수행할 수 있어 프로그램의 응답성을 높이고, 병렬 처리 성능을 향상시킵니다.
리소스 공유(Shared Resources)
여러 스레드는 같은 프로세스 내에서 메모리와 자원을 공유할 수 있습니다. 이를 통해 서로 간의 통신이 빠르고 간편해집니다.
응답성 향상(Improved Responsiveness)
UI 관련 작업에서, 백그라운드에서 시간이 오래 걸리는 작업을 별도의 스레드에서 처리함으로써 메인 스레드의 응답성을 높일 수 있습니다.
스레드의 단점
동기화 문제(Synchronization Issues)
여러 스레드가 동시에 공유 자원에 접근하면 데이터 경합(Race Condition)이나 데드락(Deadlock) 같은 문제가 발생할 수 있습니다. 이를 해결하기 위해 스레드 간 자원 접근을 동기화하는 방법이 필요합니다.
컨텍스트 스위칭 비용(Context Switching Overhead)
운영체제는 여러 스레드를 실행할 때 컨텍스트 스위칭을 사용합니다. 스레드 간에 전환할 때 CPU는 이전 스레드의 상태를 저장하고 새로운 스레드의 상태를 불러와야 하기 때문에 비용이 발생합니다.
스레드 동기화(Thread Synchronization)
여러 스레드가 동일한 자원에 접근할 때, 동기화(Synchronization)를 통해 자원의 일관성을 유지할 수 있습니다. 대표적인 동기화 방법은 뮤텍스(Mutex)와 세마포어(Semaphore)입니다.
뮤텍스(Mutex)
뮤텍스는 공유 자원을 한 번에 하나의 스레드만 사용할 수 있도록 잠그는 방법입니다. 스레드가 자원을 사용 중이면 다른 스레드는 대기해야 하며, 사용이 끝난 후 자원을 해제합니다.
세마포어(Semaphore)
세마포어는 지정된 최대 스레드 수만큼 자원에 접근할 수 있도록 허용하는 방법입니다. 하나의 자원을 여러 스레드가 동시에 사용할 수 있지만, 최대 허용 스레드 수를 초과할 수는 없습니다.
Swift에서 스레드와 동시성
Swift에서는 GCD(Grand Central Dispatch)와 OperationQueue를 통해 쉽게 멀티스레딩을 구현할 수 있습니다.
GCD(Grand Central Dispatch)
GCD는 동시성 프로그래밍을 간편하게 구현할 수 있는 API입니다. GCD를 사용하면 큐(queue)에 작업을 보내고, 해당 작업을 비동기적으로 실행할 수 있습니다.
DispatchQueue.global().async {
// 백그라운드에서 실행할 작업
print("Background thread")
}
DispatchQueue.main.async {
// 메인 스레드에서 실행할 작업
print("Main thread")
}
OperationQueue
OperationQueue는 GCD보다 더 세밀하게 작업을 제어할 수 있는 방법을 제공합니다. 여러 작업을 순차적으로 또는 병렬로 실행할 수 있으며, 작업간의 의존성을 설정할 수도 있습니다.
let queue = OperationQueue()
queue.addOperation {
print("Task 1")
}
queue.addOperation {
print("Task 2")
}
스레드 관련 문제 해결 방법
데드락
여러 스레드가 자원을 점유한 상태에서 서로 다른 스레드가 점유한 자원을 기다리면서 무한 대기 상태에 빠지는 현상입니다. 이를 방지하기 위해 락 순서를 일관되게 유지하거나 타임아웃을 설정할 수 있습니다.
레이스 컨디션(Race Condition)
여러 스레드가 동일한 자원에 동시에 접근할 때, 예상치 못한 순서로 접근하여 데이터 불일치가 발생하는 문제입니다. 뮤텍스나 동기화 메커니즘을 사용하여 해결할 수 있습니다.
스레드 활용 예시
스레드는 주로 백그라운드 작업을 처리할 때 많이 사용됩니다. 예를 들어, 네트워크 요청, 파일 다운로드, 데이터 처리 등은 메인 스레드를 차단하지 않기 위해 백그라운드 스레드에서 실행됩니다.
func fetchData() {
DispatchQueue.global().async {
// 네트워크 요청이나 오래 걸리는 작업
let data = loadDataFromServer()
DispatchQueue.main.async {
// UI 업데이트는 메인 스레드에서 처리
self.updateUI(with: data)
}
}
}
스레드는 프로세스 내에서 효율적으로 병렬 작업을 처리할 수 있도록 해주는 중요한 개념입니다. 스레드를 효과적으로 활용하면 프로그램의 성능을 크게 개선할 수 있지만, 동시에 동기화 문제와 같은 복잡한 문제도 동반될 수 있으므로 주의가 필요합니다.
'개발 용어' 카테고리의 다른 글
동기 (Synchronization) (2) | 2024.09.26 |
---|---|
멀티스레딩 (Multithreading) (5) | 2024.09.25 |
트러블슈팅 (Troubleshooting) (7) | 2024.09.24 |
디버깅 (Debugging) (2) | 2024.09.19 |
CI/CD (5) | 2024.09.18 |