2015. 1. 26.
[OS]쓰레드(Thread)와 Critical Section(임계영역)
프로세스와 메인 쓰레드(main thread)
쓰레드는 프로세스에 존재하는 실행 흐름 중 하나이다. 그런 실행 흐름 중에는 우리가 흔히 main() 함수라고 부르는 쓰레드가 존재한다. 어떤 프로그램을 실행시키면 main() 함수가 실행되는데, 이는 다시 말해 main 쓰레드가 실행된다는 것을 의미한다. 만약 main 쓰레드를 통해서 다른 쓰레드를 만들어서 다른 쓰레드로 하여금 특정한 일을 시키면 어떨까? 이 상황은 아래의 그림과 같다.(쓰레드의 의미 중에 실, 가닥이라는 의미도 있다)
ThreadProc() 함수 바로 앞에 선언된 total은 static 변수이다. static 변수는 메모리의 data 영역에 존재하고, thread는 이를 공유하게 된다. 결국 3개의 쓰레드는 모두 static 변수 total에 접근가능하다. 이런 특성때문에 쓰레드는 IPC와 같은 방법으로 통신할 필요가 없다.
하지만 위 total 변수는 쓰레드의 동시접근 문제를 발생시킬 수 있다.
쓰레드는 결국 스케줄러에 의해 번갈아가며 실행된다. 이 과정에서 컨텍스트 스위칭은 불가피하게 발생한다. 프로세스는 독립적인 메모리 공간을 가지기 때문에 컨텍스트 스위칭 과정에서 데이터가 변경되지는 않는다. 하지만 쓰레드 간의 컨텍스트 스위칭은 상황이 다르다. 컨텍스트 스위칭 상황에서 쓰레드는 프로그램 라인 단위로 이뤄지지 않는다. 예를 들어 A() 함수가 실행 중 일 때는 절대 컨텍스트 스위칭이 발생하지 않는다고 생각하면 안 된다. 실행 중인 쓰레드의 변경은 매우 빈번하게 발생하며, 우리가 이에 쓰레드의 실행 흐름을 예측해서 제어하는 것은 불가능하다.
그래서 둘 이상의 쓰레드가 위의 total과 같이 같은 메모리 영역을 동시에 참조하면 문제를 일으킬 수 있다. 우리는 덧셈이 올바르게 완료될 것으로 예상하지만, 이는 우리의 기대일 뿐이다. 1 + 2의 값을 3이라고 저장하지도 못한 상태에서 33,334 + 33,335를 계산하는 쓰레드가 실행될지도 모른다. 이렇게 되면 결국 total의 값은 3만큼 누락된다.
임계영역(Critical Section)
위 코드의 worker 쓰레드 함수 내부의 total을 둘 이상의 쓰레드가 동시에 실행할 경우 문제가 발생할 수 있다. 이런 문제를 일으킬 수 있는 코드 블럭을 임계영역이라고 한다. 다시 말해 임계영역은 배타적 접근(한 순간에 하나의 쓰레드만 접근)이 요구되는 공유 리소스(전역변수, static 변수 등)에 접근하는 코드 블럭을 의미한다.
'OS' 카테고리의 다른 글
컨텍스트 스위칭 (0) | 2018.08.08 |
---|---|
OS 학습 참고 (0) | 2018.08.08 |
메모리 관점에서 본 쓰레드(thread) (0) | 2018.08.08 |
세마포어 뮤텍스 (0) | 2018.08.08 |