-->
OSTEP 26 Concurrency and Threads
Published: | at 오전 02:44 Table of contents
Open Table of contents
병행성: 개요
- 병행성의 기본은 운영체제가 하나의 물리적 CPU를 여러 개의 가상 CPU로 확장하여 프로그램들이 동시에 실행되는 것처럼 보이게 하는 것이다.
- 이번 장에서는 쓰레드라는 새로운 개념을 소개한다.
- 쓰레드는 프로세스와 유사하지만 주소 공간을 공유하므로 동일한 데이터에 접근할 수 있다.
- 쓰레드는 프로그램 카운터와 레지스터를 가지고 있으며, 다른 쓰레드와 문맥 교환을 할 수 있다.
예제: 쓰레드 생성
- 이 예제에서는 두 개의 독립적인 쓰레드를 생성하여 각각 “A”와 “B”를 출력한다.
- 메인 프로그램은
mythread()
함수를 실행하는 두 쓰레드를 생성하며, 각 쓰레드는 서로 다른 인자를 받는다.
- 쓰레드 생성 후 메인 쓰레드는
pthread_join()
함수를 호출하여 특정 쓰레드의 동작이 종료될 때까지 대기한다.
훨씬 더 어려운 이유: 데이터의 공유
- 쓰레드가 공유 데이터에 접근하고 상호작용하는 과정을 설명한다.
- 예제는 전역 공유 변수
counter
를 갱신하는 두 쓰레드를 사용한다.
- 각 쓰레드는
counter
에 천만 번 값을 더하는 작업을 수행하며, 이 과정에서 발생하는 데이터 공유의 복잡성과 문제점을 탐구한다.
제어 없는 스케줄링
- 이 부분에서는
counter
변수를 갱신하는 코드의 실행 순서와 그로 인해 발생하는 문제를 설명한다.
- 예를 들어, 두 쓰레드가 동시에 같은 변수를 수정할 때 발생하는 경쟁 조건(race condition)과 이로 인한 비결정적 결과를 다룬다.
- 이는 쓰레드의 실행 순서가 예측 불가능하며, 매 실행마다 다른 결과를 낳을 수 있다는 것을 의미한다.
원자성에 대한 바람
- 원자성은 한 번에 하나의 쓰레드만이 임계 영역(critical section)에 접근하도록 보장하는 개념이다.
- 이를 위해 강력한 단일 명령어를 사용하여 인터럽트의 발생을 차단하고, 예상한 동작을 수행할 수 있는 방법을 탐구한다.
- 이러한 명령어는 원자적으로 실행되며, 인터럽트가 발생하지 않도록 보장한다.
또 다른 문제: 상대 기다리기
- 병행 프로그래밍에서는 종종 한 쓰레드가 다른 쓰레드의 특정 동작이 끝날 때까지 기다려야 하는 상황이 발생한다.
- 이는 예를 들어 프로세스가 디스크 I/O 요청 후 응답을 기다리는 상황과 유사하다.
- 멀티 쓰레드 프로그램에서 이러한 상황을 다루기 위한 동기화 함수 및 잠자기/깨우기 동작에 대한 지원 기법을 다룬다.
정리: 왜 운영체제에서?
- 운영체제의 역사적 관점에서 병행 프로그래밍의 필요성을 설명한다. 운영체제는 병행 프로그래밍의 첫 사례였으며, 여러 기법이 운영체제 내에서 개발되었다.
- 병행 프로그래밍에서 공유 자원을 다루는 코드는 임계 영역이 되며, 이를 올바르게 관리하기 위한 적절한 동기화 함수의 사용이 필수적이다.