CPU 점유
태스크들은 각각 CPU의 자원을 점유하여 프로그램을 실행하거나 처리한다라고 개념 정리를 했다.
그럼 태스크들은 어떤 식으로 CPU 자원을 점유하고 어떤 식으로 처리하는지 알아볼 필요가 있다.
CPU는 한 번에 한 가지 일에만 집중하여 수행한다.
하지만 막상 컴퓨터를 눈으로 보았을 때 CPU는 여러 가지 작업을 처리하는 것처럼 보인다. 정말로 동시에 여러 작업을 처리하는지 의문이 든다.
그 의문을 해결하기 위해 다음과 같은 개념 정리가 필요하다.
Multi-Tasking
말 그대로 "여러 작업"을 뜻한다.
이미 보았듯이 CPU는 한 번에 한 가지 일만 수행하도록 되어있지만 Multi-tasking을 통해 여러 작업을 처리할 수 있게 된다.
"그렇다면 Multi-tasking은 한 번에 여러 작업을 처리할 수 있게 하나?"
그건 아니다.
CPU가 매우 빠르게 처리하여 여러 작업이 한 번에 처리되는 것처럼 보일 뿐 순차적으로 처리한다.
그렇다면 태스크는 CPU에서 어떤 자원을 통해 처리가 되는 걸까.
그걸 알려면 메모리 계층구조에 대해 살펴보아야 한다.

여기서 프로그램을 실행시키려면 레지스터가 필요하다. 이러한 레지스터들은 범용적으로 여러 연산처리에 활용되기 때문에 범용 레지스터라고 불린다.
하지만 레지스터는 한정적인 자원이라 태스크들이 자원(레지스터)을 점유하기 위해 서로 경쟁할 것이다.
여기서 문제가 발생한다.
A태스크가 자원을 점유하여 처리 중에 B태스크가 해당 자원을 점유하여 처리해 버린다면 사용자는 기대했던 결과와 다른 처리가 되어 말도 안 되는 결과 값이 나와버린다.
이러한 문제를 '데이터 무결성이 깨졌다'라고 한다.
데이터 무결성
데이터 무결성이란 말 그대로 데이터의 일관성을 유지하고 보증하는 것이다.
데이터 무결성이 깨질 경우 기대했던 결과와 다른 결과를 보여주며, 해당 프로그램은 클라이언트로부터 신뢰를 얻을 수 없다.
대단히 중요한 문제이다.
그렇다면 이러한 데이터는 어디에 있나?
Critical Section이라는 공간에 배치되어있다.
Critical Section
Critical Section에서는 스레드들 간에 메모리를 공유할 수 있는 공간 즉 여러 스레드가 한 번에 접근할 수 있는 공유 메모리 공간이다.
위에서 보았듯이 스레드들이 자원을 점유하고 처리하면서 공유한 데이터의 값이 변경되면서 발생하는 문제가 바로 데이터 무결성이 깨지는 문제이다.
"그렇다면 이와 같은 문제는 처리하지 못하나?"
아니다 Context Switching을 통해 처리할 수 있다.
Context Switching
그럼 우리는 생각해 볼 수 있다.
A태스크가 처리하고 있던 데이터가 변형되지 않으려면 어딘가 다른 공간에 저장해두면 데이터에 접근하지 못하니깐 데이터 무결성이 보장되지 않나?
맞다. A태스크가 자원을 점유하고 처리하면 해당 정보를 메모리 A에 넣어두고 처리하는 동안 B태스크가 자원을 점유하면 태스크 B 데이터 정보를 가져와 처리하고 메모리 B에 넣어둔다. 이런 식으로 작업을 완료하게 되면 클라이언트가 기대하던 결과에 맞게 나타난다.
하지만 태스크가 처리하던 자원이 강제로 다른 태스크에게 넘어가는 것 때문에 여전히 불안한 감이 있다.
이러한 것을 해결할 수 있는 Mutex, Semaphore기법이 있다.
Mutex / Semaphore
우리의 일상생활에서 한번 알아보자
본인이 화장실을 이용하기 위해서 문을 잠그고 이용할 것이다. 이용 중 다른 사람이 화장실을 사용하려 하는데 현재 화장실 문이 잠겨있어 이용하지 못하고 들어간 사람이 다 이용한 후 문이 열리면 그때서야 사용할 수 있다.
이러한 방식을 그대로 프로그래밍에 적용할 수 있다.
태스크 A가 자원을 점유 중일 땐 Lock을 걸어 다른 태스크가 접근하지 못하도록 막는다.
태스크 A가 모든 작업을 끝나고 Unlock을 하면 태스크 B가 자원을 점유하고 Lock을 건다. 이러한 방식으로 처리하면 더욱 안전하게 데이터 무결성을 보장할 수 있다.
하지만 이러한 방식은 한 태스크가 Lock과 Unlock을 하면서 처리속도가 느려진다. 그러한 이유는 모든 처리는 메모리에서 처리된다. lock과 unlock도 메모리에서 처리된다. 이 말은 즉 메모리 계층구조를 살펴보면 메모리는 하드디스크보다 더 빠르지만 그래도 많이 느리다. 안 그래도 느린데 메모리에서 처리하기 때문에 더 느려진다.
처리속도를 증가시키려면 코드 작성 시 불필요한 for문이라던지 반복적으로 처리하는 부분에서 Lock, Unlock기능을 하지 않도록 하면 처리속도가 상당히 증가한 걸 볼 수 있다.