쓰레드(Thread)
1. 쓰레드란?
- **쓰레드(Thread)**는 프로그램 내에서 작업을 실행하는 최소 실행 단위.
- 하나의 프로그램(프로세스)은 기본적으로 하나의 메인 쓰레드(fun main(0 메인함수)에서 실행되며, 이를 통해 모든 작업이 처리됨.
- 추가 쓰레드를 생성하면 여러 작업을 동시에 처리할 수 있어 **동시성(Concurrency)**을 구현할 수 있음.
2. 쓰레드의 기본 개념
- 프로세스(Process):
- 실행 중인 프로그램으로, 운영체제(OS)에서 메모리와 CPU를 할당받아 독립적으로 실행됨.
- 각 프로세스는 독립된 메모리 공간(코드, 데이터, 힙, 스택)을 가짐.
- 쓰레드(Thread):
- 프로세스 내에서 실행되는 작은 작업 단위.
- 스택 메모리를 독립적으로 사용하지만, 힙 메모리(공유 자원)는 다른 쓰레드와 공유.
- 쓰레드의 메모리 구조:
- 스택(Stack): 쓰레드마다 독립된 실행 컨텍스트를 저장.
- 힙(Heap): 모든 쓰레드가 공유하는 메모리 공간.
- 코드/데이터 영역: 프로그램의 실행 코드와 상수 저장.
3. 쓰레드의 특징
특징 | 설명 |
병렬 실행 | 여러 쓰레드가 동시에 실행 가능하여, 작업 처리 속도와 효율성을 높임. |
스택 독립성 | 각 쓰레드는 독립된 스택 메모리를 가지므로, 실행 컨텍스트를 개별적으로 관리. |
공유 자원 관리 | 쓰레드는 힙 메모리를 공유하므로, 공유 자원 접근 시 동기화(Synchronization)가 필요. |
컨텍스트 스위칭 | CPU가 여러 쓰레드 사이를 전환하며 실행. 전환 비용(오버헤드)이 발생. |
4. 쓰레드의 필요성
- 동시성(Concurrency) 구현:
- 하나의 작업을 여러 단위로 나누어 동시에 처리.
- 예: UI 처리 중 파일 다운로드.
- 대기 시간 최소화:
- 시간이 오래 걸리는 작업(네트워크 요청, 파일 입출력 등) 동안 다른 작업을 중단 없이 실행.
- 프로그램 효율성 향상:
- 멀티코어 CPU에서 여러 쓰레드를 실행하면 자원을 효율적으로 활용 가능.
5. 쓰레드를 사용하는 주요 사례
- 게임:
- 캐릭터의 움직임, 효과음, 사용자 입력 처리를 동시에 수행.
- 멀티미디어 애플리케이션:
- 비디오 재생 중 오디오 출력과 자막 표시를 병렬로 실행.
- 네트워크 서버:
- 여러 클라이언트 요청을 동시에 처리.
- 경쟁 환경:
- 경마 프로그램처럼 여러 개체가 동시에 움직이고 결과를 경쟁.
6. 쓰레드의 구현
1) Kotlin에서 쓰레드 생성
fun main() {
thread(start = true) {
println("Thread 1: 실행 중")
}
thread(start = true) {
println("Thread 2: 실행 중")
}
}
2) 쓰레드 경쟁 예제
fun main() {
thread(start = true) {
for (i in 1..10) {
println("Thread 1: $i")
Thread.sleep(500) // 0.5초 대기
}
}
thread(start = true) {
for (i in 50..60) {
println("Thread 2: $i")
Thread.sleep(500) // 0.5초 대기
}
}
}
3) 쓰레드 동기화 문제 해결
- 여러 쓰레드가 공유 자원을 동시에 접근할 경우, 데이터 충돌 문제 발생 가능.
- 해결 방법: synchronized 키워드로 동기화 처리.
val lock = Any()
var sharedResource = 0
fun main() {
thread(start = true) {
synchronized(lock) {
for (i in 1..5) {
sharedResource++
println("Thread 1: $sharedResource")
}
}
}
thread(start = true) {
synchronized(lock) {
for (i in 1..5) {
sharedResource++
println("Thread 2: $sharedResource")
}
}
}
}
7. 쓰레드의 장단점
장점 | 단점 |
병렬 처리로 작업 처리 속도가 향상. | 컨텍스트 스위칭으로 인한 성능 오버헤드 발생. |
대기 시간이 긴 작업(I/O 작업)을 처리하면서 다른 작업을 실행 가능. | 동기화 문제로 인해 데이터 충돌 및 데드락 발생 가능. |
멀티코어 CPU 환경에서 성능 효율성을 극대화. | 쓰레드 수가 많아지면 메모리 사용량 증가. |
8. 추가 학습이 필요한 주제
- 코루틴 (Coroutine):
- 쓰레드보다 가볍고 효율적인 비동기 프로그래밍 방식.
- Kotlin의 대표적인 비동기 처리 도구.
- 동기화(Synchronization):
- 공유 자원 접근 시 발생하는 문제를 해결하기 위한 기술.
- Mutex, Semaphore, Volatile 등.
- 컨텍스트 스위칭(Context Switching):
- 쓰레드 간 전환 시 발생하는 비용과 효율성 최적화 방법.
- 멀티쓰레드 디버깅:
- 복잡한 쓰레드 환경에서의 오류 해결 방법.
- Reactive Programming:
- 비동기 데이터를 처리하는 프로그래밍 패러다임. (Ex: RxJava, Project Reactor)
9. 결론
쓰레드는 동시성과 병렬성을 구현하기 위한 강력한 도구입니다. 하지만 쓰레드를 잘못 설계하면 데이터 충돌, 데드락 등 복잡한 문제가 발생할 수 있습니다. 쓰레드의 한계를 보완하기 위해 코루틴 같은 최신 기술도 함께 학습하면 더욱 효율적인 프로그래밍이 가능합니다.
'CS ( Computer Science ) > 운영 체제 (Operating Systems)' 카테고리의 다른 글
[OS] 자원 관리 (0) | 2025.02.20 |
---|---|
[OS] 코루틴 (0) | 2025.02.19 |
[OS] 비동기 프로그래밍 (0) | 2025.02.18 |
[OS] 프로세스와 쓰레드 (0) | 2024.11.24 |