꾸준한 개발자

계속적인 성장을 추구하는 개발자입니다. 꾸준함을 추구합니다.

계속 쓰는 개발 노트

운영체제 (OS)

스레드 동기화 문제

gold_dragon 2021. 4. 22. 20:57

스레드는 실행 순서가 정해져있지 않습니다. 그렇다보니 순서가 꼬일 수 있는 오류가 있습니다. 이러한 오류를 동기화(synchronization) 이슈라고 합니다. 그래서 스레드 관리가 필요합니다. 동기화 이슈가 생기면 디버깅하기도 어렵습니다.

패스트캠퍼스 운영체제 강의 참조

위 코드는 50개의 스레드를 생성하고 실행합니다. 스레드를 다 실행하고 나서 메인 스레드로 돌아오게 됩니다.  join() 함수를 통해서 모든 스레드가 끝날 때까지 기다리게됩니다. 실제로 위 코드를 실행하면 실행할 때마다 결과값이 다릅니다.

만약 스레드 1이 덧셈까지만 동작하고 context switching 되고 다음 스레드 2에서도 덧셈까지만 하고 context switching이 되면서 스레드 1로 돌아오면 그때 g_count를 저장 하고 다시 스레드 2로 돌아가서 g_count를 저장하게 되면, 덧셈은 두 번 했지만 g_count에는 1이 저장됩니다.  예상 결과값 500000이 아닌 그보다 작은 값이 나오게 됩니다.

 

이러한 동기화 문제를 해결할 수 있는 방법으로는 matual exclusion이 있습니다.

동기화 이슈

작업들 사이에 실행 시기를 맞추는 것을 동기화라 합니다. 여러 스레드가 동일한 자원에 접근할 때 동기화 이슈가 발생하는데, 동일한 자원을 여러 스레드가 동시에 수정하려고 할 때, 각각 스레드 결과에 영향을 주는데 이를 동기화 이슈라 합니다.

 

이를 해결하기 위해서는 실행 시기를 맞추어야 되는데, 여러 스레드가 변경하는 공유 변수에 대해 Exclusive Access를 부여해서 어느 한 스레드가 공유 변수를 갱신하는 동안 다른 스레드가 동시에 접근하지 못하도록 막아줘야 됩니다. 이를 Mutual exclusion(상호 배제)라 합니다.

Mutex와 세마포어(semaphore)

Critical Section(임계 구역)에 대한 접근을 막기 위해 Locking 매커니즘이 필요합니다.

 

임계 구역에 하나의 스레드만 들어갈 수 있는 것을 Mutex(binary semaphore)라 하고, 임계 구역에 여러 스레드가 들어가는데 couter를 둬서 동시에 리소스에 접근할 수 있는 허용 가능한 스레드 수를 제어하는 것을 semaphore라고 합니다.

 

세마포어 sudo 코드를 보면 다음과 같습니다.

P: 검사 (임계 영역에 들어갈 때) -> S값이 1 이상이면, 임계 영역 진입 후, S값 1을 차감합니다. S값이 0이면 대기합니다.

V: 증가 (임계 영역에서 나올 때) -> S값을 1 더하고, 임계 영역을 나옵니다.

S: 세마포어 값 (초기 값만큼 여러 프로세스가 동시 임계 영역 접근 가능) -> 스레드 수를 설정할 수 있습니다.

 

세마포어의 바쁜 대기의 경우 대기큐로 보완할 수 있습니다. S가 음수일 경우 바쁜 대기 대신 대기큐에 넣어놓습니다.