개요
- 한 순간에 하나의 명령어만 실행하는 프로그램과 다르게 멀티 스레드 프로그램은 하나 이상의 실행 지점을 가짐
- 각 스레드는 프로세스와 유사하지만 스레드들은 주소 공간을 공유하기 때문에 동일한 값에 접근할 수 있음
- 두 개의 스레드가 하나의 프로세서에서 실행 중이면 실행하고자 하는 스레드는 반드시 문맥 교환을 통해서 교체되어야 함
- 스레드 간의 문맥 교환은 T1이 사용하던 레지스터를 저장하고 T2가 사용하던 레지스터의 내용으로 복원한다는 점에서 프로세스의 문맥 교환과 유사
- 프로세스의 문맥 교환을 할 때 프로세스의 상태를 프로세스 제어 블럭(PCB : Process Control Block)에 저장하듯이 프로세스의 쓰레드들의 상태를 저장하기 위해서는 하나 이상의 스레드 제어 블럭(TCB : Thread Control Block)이 필요
- 차이는 스레드 간의 문맥 교환에는 주소 공간을 그대로 사용하면 됨
- 단일 스레드 프로세스 -> 스택 하나
- 멀티 스레드 프로세스 -> 스레드마다 스택 할당
- 주소 공간이 깔끔하지 않음
- 이전처럼 더 이상 공간이 없는 경우에만 문제가 생기는 것이 아님
- 재귀 호출을 많이 하는 것과 같은 경우를 제외하면 대부분의 경우 문제가 생기진 않음
쓰레드 생성
- 스케줄러의 동작에 따라 스레드의 실행 가능 순서가 다양할 수 있음
- 스레드1 생성 -> 스레드2 생성 -> 스레드1 실행 -> 스레드2 실행
- 스레드1 생성 -> 스레드1 실행 -> 스레드2 생성 -> 스레드2 실행
- 생성이 먼저 됐더라도 나중에 실행될 수도 있음
- 함수 호출에서는 함수 실행 후에 caller에게 리턴
- 스레드는 실행할 명령어들을 갖고 있는 새로운 스레드가 생성되고, 생성된 스레드는 caller와 별개로 실행
- 생성 함수가 리턴되기 전에 실행될 수도 그 이후에 실행될 수도 있음
데이터의 공유
- counter 변수의 주소의 위치를 0x8049a1c라고 가정
현재 값을 50이라 가정
- 각 줄을 ①, ②, ③이라고 하자
- 스레드1이 ①, ②를 수행 -> eax는 51
- 인터럽트가 발생해 스레드1이 TCB에 저장
- ③을 수행하기 전이라 스레드2는 50인 값을 가져와서 코드를 수행 -> counter는 51
- 다시 문맥 교환이 일어나면 스레드1에서는 51을 대입
- 최종적으로 52였어야하는 값이 51
- 경쟁 조건(race condition) : 명령어의 실행 순서에 따라 결과가 달라지는 상황
- 컴퓨터의 작동에서 일반적으로 발생하는 결정적 결과와 달리 결과를 알 수 없거나 실행 때마다 결과가 다른 경우를 비결정적인 결과라고 함
- 임계 영역(critical section) : 공유 변수(일반적으로는 공유 자원)를 접근하고 하나 이상의 스레드에서 동시에 실행되면 안되는 코드
- 하나의 스레드가 임계영역 내의 코드를 실행 중일 때는 다른 스레드가 실행할 수 없도록 보장하는 상호 배제(mutual exclusion) 속성이 필요
원자성
- 원자적으로 실행 : 전부 실행되거나 하나도 실행 안되거나
- 임계 영역 문제 해결 방법 중 하나는 강력한 명령어 한 개로 의도한 동작을 수행
- 일반적인 상황에서 하나의 명령어로 대신할 수 있는 명령어는 없다고 봐야 함