하지만 두 번째 경우에는 g_count에 값을 저장하기 전에 컨텍스트 스위칭이 일어납니다. 세 번째 레지스터와 메모리를 보면 스레드 2가 CPU를 점유하고 레지스터에 g_count 값을 가져오면 0이 되겠지요. 네 번째에서 1을 더해 레지스터 값이 1이 되고 연산 결과를 g_count에 저장하기 전에 컨텍스트 스위칭이 일어납니다. 다섯 번째를 보면 스레드 1이 CPU를 점유한 다음 이전 레지스터 값인 1을 복원하고 이전 상태에 이어 연산을 마무리합니다. 레지스터에 있던 값을 g_count에 저장하므로 g_count는 1이 됩니다.
여섯 번째를 보면 스레드 2로 컨텍스트 스위칭이 일어난 다음 스레드 2도 이전 상태에 이어 연산을 마무리합니다. 레지스터에 저장되어 있는 값을 g_count에 저장합니다. 따라서 최종 g_count 값은 1이 됩니다. 각 스레드의 관점에서 보면 스레드는 첫 번째 경우나 두 번째 경우 모두 g_count 값에 1을 더하는 같은 연산을 합니다. 하지만 컨텍스트 스위칭이 언제 일어나는지에 따라 전혀 다른 결과가 나옵니다. 이처럼 스레드 여러 개가 공유 자원에 동시에 접근하는 것을 ‘경쟁 조건(race condition)’이라고 합니다.
보통 경쟁 조건은 심각한 문제를 일으킵니다. 이번 예제에서는 여러 스레드가 g_count에 단순히 접근만 하고 값을 변경하지 않으면 아무런 문제도 발생하지 않습니다. 하지만 스레드 안에 있는 코드가 g_count 값에 1을 더하려고 하면 문제가 발생합니다. 이처럼 공유 자원에 접근해 변경을 시도하는 코드를 임계 영역(critical section)이라고 합니다. 임계 영역에서 일어나는 문제를 어떻게 해결할지 이어서 알아봅시다.