스레드는 프로세스 내부에서 진행되고 있는 작업의 단위이자 갈래이다. 프로세스 내부에서 2개 이상의 스레드의 흐림이 발생하면 멀티-스레딩(Multi-Threading)이라고 한다.
멀티 스레딩을 이야기 할때 빠지지 않는 말이 동시성(Concurreny)과 동기화 이슈이다.
프로세스가 시작되면서 사용할 수 있는 메모리 공간을 할당 받는다. 그리고 프로세스 내부에는 여러 스레드들이 생성되게 되는데 이때 스레드들은 제한된 프로세스의 내부 메모리 크기 내에서 자원을 사용한다.
동기화는 동시에 접근해서는 안되는 자원에 동시에 접근하지 않도록 제어하는 과정, 또는 특정 조건이 만족해야 실행할 수 있는 상황에서 올바른 순서대로 실행하게 하는 것을 의미한다.
동시에 접근해서는 안되는 자원에 동시에 접근하지 못하도록 만드는 도구, 상호 배제를 위한 동기화 도구.
공유된 자원의 데이터 또는 임계영역
등에 하나의 프로세스나 스레드가 접근하는 것을 막아줌
. (동기화 대상이 하나)
acquire
함수 - 임계 구역이 잠겨있으면 임계 구역을 반복하며 확인하고, 잠겨있지 않으면 임계 구역을 잠근다.
acquire() {
while ( lock == true ) ;
lock == true;
}
→ 임계 구역이 잠겨있는지 반복해서 확인하는 대기 방식을 Busy Wait
이라고 한다.
release
함수 - 임계 구역의 작업이 끝난 후 호출하는 함수. 잠긴 임계구역을 열어주는 함수.
release() {
lock = false;
}
💡 임계 구역
공유된 자원의 데이터 혹은 임계영역
에 여러 프로세스나 스레드가 접근하는 것을 막음
. (동기화 대상이 하나 이상)
공유된 여러 개의 자원에 대한 접근을 제한하는 방법으로서, 원자적 함수로 조작되는 정수 변수를 말한다.
정수 변수는 임계 구역
에 들어가기 전에 수행하는 P()
와 임계 구역을 나올 때 실행되는 V()
에 의해 변경된다.이때 두 함수의 연산은 원자성을 유지해주어야 한다.
P()
, wait()
wait() {
while ( S <= 0 ) // 임계 구역에 들어올 수 있는 프로세스가 없으면
; // 사용 가능한 자원을 반복적으로 확인
S--; // 가용 자원이 있으면 자원의 개수를 하나 줄인다.
}
V()
, signal()
signal() {
S++; // 임계 구역에서 작업을 마치고 S를 1 추가한다.
}
→ Mutex와 마찬가지로 위 방식을 통해서 Busy Wait 상태가 발견된다. Busy Wait의 경우 가용 리소스를 반복문을 지속해서 사용하면서 CPU의 리소스를 계속 사용함
→ Busy Wait의 단점을 보완하는 방식. 사용할 수 있는 리소스가 없을 때, 프로세스를 대기 상태로 전환하고 해당 프로세스의 PCB를 대기 큐에 넣음
→ 이후 가용 상태를 알리는 signal()함수로 대기 상태인 프로세스를 준비 상태로 변경하고 준비 큐로 옮겨 리소스를 사용할 수 있게 함
P()
, wait()
wait() {
S--;
if ( S < 0 ) { // 가용 리소스가 없을 때
add this process to Queue; // 프로세스를 대기 큐에 넣고
sleep(); // 프로세스를 대기 상태로 전환
}
}
V()
, signal()
signal() {
S++;
if ( S <= 0 ) { // 대기 큐에서 프로세스를 뺀다면
remove process from Queue // 대기 큐에서 프로세스를 제거
wakeup(p); // 프로세스를 준비 상태로 전환
}
}
wait(P), signal(V) 함수의 경우 독립적이기 때문에 잘못 사용하는 경우 문제가 발생한다.
P -> 임계 구역 -> P
: 프로세스가 P함수에 진입 후 빠져나올 수 없다. 동시에 다른 프로세스/스레드가 임계 구역에 들어올 수 없는 상태기 때문에 DeadLock(교착상태)
에 빠진다.V → 임계 구역 → P
: 2개의 프로세스가 동시에 임계구역에 들어가는 경우 상호 배제(Mutual Exclusion)를 보장할 수 없다.Semaphore는 wait과 signal을 개별로 명시해주어야 하는데, 이 과정이 번거롭거나 혹여, 두 함수의 순서가 꼬이는 상황이 발생하게 되면 원하지 않는 결과를 얻게 될 수 있다.
이런 부작용을 안전하게 하기 위해 Monitor라는 새로운 동기화 도구가 나왔다. 모니터를 사용하면 공유 자원에 접근은 공유 자원과 연결된 통로(인터페이스)를 통해서만 접근할 수 있도록 한다.
여러 프로세스가 동시에 데이터에 접근할 때 실행 순서에 따라 결과 값이 달라지는 현상
Race Condition는 리소스에 여러 프로세스가 자원을 공유할 때 처리 순서에 따라 결과가 달라질 수 있다는 점과 리소스의 일관성을 보장할 수 없다는 점에서 문제가 발생할 수 있음
리소스를 공유하는 과정에서 서로 다른 프로세스의 요구가 얽혀서 어느 한 쪽의 프로세스도 자원을 이용하지 못하고 모두 대기상태에 빠지는 것을 의미
- 조건
- 상호배재 ( Mutual Exclusion )
→ 한 자원에 하나의 스레드만 접근 가능
2. 점유대기 ( Hold and Wait )
→ 공유 자원에 대한 락을 통해 점유하고 있는 상황에서 다른 자원에 대한 사용을 기다리는 상태
3. 비선점 ( No Preemption )
→ 필요한 리소스를 다른 스레드가 선점하고 있어 스레드 도중에 뺏을 방법이 없는 상태
4. 순환대기 ( Circular Wait )
→ 여러 프로세스/스레드가 자원을 요청하는 구조가 순환하는 형태