1. 동기화 문제란?
여러 프로세스 또는 여러 스레드가 동시에 실행될 때 발생하는 데이터 일관성 문제를 동기화 문제라고 한다.
대표적으로 공유 메모리에 여러 스레드가 동시에 접근해서 값을 변경할 때 연산 결과 출력이 예상치 못한 값으로 나오는 공유 메모리 동기화 문제(Race condition)를 대표적인 동기화 문제로 볼 수 있다.
2. Race Condition / 경쟁 상태
여러개의 프로세스 또는 스레드가 하나의 공유 자원에 동시에 접근할 때 생기는 문제를 말한다.
아래 코드를 보면 스레드 두개를 선언하고 전역으로 선언한 sum이라는 변수에 스레드 두개가 동시에 접근하여 sum이라는 전역 변수에 값을 1씩 증가시키는 코드이다. 뇌버깅을 돌려보면 두개의 스레드에서 1씩 30000번씩 증가시키기 때문에 마지막에 sum을 출력하면 60000만이 나와야 할 것 같다. 아래 결과를 보자
#include <pthread.h>
#include <stdio.h>
int sum = 0;
void *run(void *param) {
int i;
for (i = 0; i < 30000; i++)
sum++;
pthread_exit(0);
}
int main() {
pthread_t tid1, tid2;
pthread_create(&tid1, NULL, run, NULL);
pthread_create(&tid2, NULL, run, NULL);
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
printf("%d\n", sum);
}
결과를 보면 아래와 같다. 정상적으로 나올 때도 있지만 29951처럼 예상치 못한 값이 튀어 나올때가 있다.
이렇게 예상하지 못한 값이 나온 이유는 만약 스레드가 전역변수에 접근해서
sum = 200 > thread1
sum++; > thread1 동시에 sum = 200 > thread2접근 (후치연산이기 때문에 200인 상태로 sum에 있는 200을 가져감)
sum++ > thread2 -> 원래라면 thread1이 201을 만들었으니 thread2가 값을 증가시키면 202를 만들어야 하지만 중간에 값이 씹혀서 동일하게 201로 만들고 sum에 저장함.
이런 과정을 통해 값이 개발자가 예상하지 못한 값이 때때로 나오는 경우가 발생한다.
3. Critical Section / 임계 영역
임계 영역이란 여러 프로세스 또는 스레드가 접근해서 값을 변경할 수 있는 (코드의)공유된 데이터 영역을 임계 영역이라고 한다.
Race condition에서 보여준 예시의 sum이 바로 main.c의 임계영역이라고 볼 수 있다. 결론적으로 Race condition문제는Critical Section에 여러 프로세스 또는 스레드가 접근해서 연산을 하기 때문에 발생하는 문제이므로 Critical section을 통제해야 한다.
3-1.Critical Section의 구조
프로세스도 하나의 코드기 때문에 임계영역 기준으로 섹션을 나눠보자면 아래와 같이 나눌 수 있다.
Entry section : 임계 영역에 들어가는 부분, 접근 여부 확인 가능 구간
Critical section : 실제로 Data inconsistency 문제가 발생할 수 있는 구간
Exit section : 임계 영역에서 빠져나오는 부분, 임계영역 작업이 끝난 후 작업 종료 여부를 다른 프로세스, 스레드한테 알려주는 구간
Non-Critical Section or Remainder Section : Data inconsistency가 발생하지 않는 구역. 위의 3가지를 제외한 부분이 전부 해당됨
4. Critical section problem solution
위에서 살펴본 임계영역에서 발생한 문제를 해결하기 위해서는 아래의 세가지 조건을 만족해야한다
1. Mutual Exclusion (상호 배제 - Race Condition 해결)
- 하나의 프로세스, 스레드가 임계영역에서 작업중이면 다른 프로세스는 임계 영역에 들어가지 못하게, 실행할 수 없게 하는 것. 상호 배제를 지키기 위해서는 Synchronous하게 실행하면 된다. 한 프로세스나 스레드가 임계영역에 들어간 이상 다른 프로세스는 프로세스가 작업이 끝날 때 까지 임계 영역에 들어오지 못하도록 하는것이다.
2. Progress (진행 - Deadlock 해결)
Progress란 Deadlock이라고 불리는 교착 상태를 해결해야 한다. 현재 CPU에는 어떠한 프로세스도 실행하고 있지 않지만 프로세스들이 CPU의 자원을 할당받지 못하고 기다리며 무한정 대기하고 있는 상황이다. 그래서 아무것도 실행이 되지않고 멈춘 상태이다.
그래서 임계영역 문제를 해결하기 위해서는 간단히 설명한 위의 교착 상태를 풀어서 무한대기 하는 상태를 벗어나 프로세스들이 실행될 수 있어야 한다.
3. Bounded Waiting (유한 대기 - 기아 상태 해결)
프로세스가 실행 완료될 때 까지 기다리게 되면 현재 실행되고 있는 프로세스의 CPU burst time이 엄청나게 긴 프로세스이면 다른 프로세스는 전혀 실행되지 못하고 기아상태에 빠지게 된다. 그래서 Bounded waiting을 적용하여 일정 시간이 지나면 다른 프로세스에게 자원을 양보해줘야 한다.
5. 비선점형 커널 VS 선점형 커널
1. 비선점형 커널
- 현재 실행 중인 프로세스 또는 스레드가 완료되거나 대기 상태로 전환될 때까지 다른 프로세스에세 CPU 자원을 넘겨주지 않는 커널이다.
- 한번 CPU를 점유하면 작업을 완료할 때까지 자원을 넘겨주지 않으며 우선순위나 Time sharing에 따른 선점이 발생하지 않는다.
- 비선점형 커널에서는 Race condition과 같은 동기화 문제가 발생할 일이 없지만 성능이 매우 안 좋아질 수 있다.
2. 선점형 커널
- 현재 실행중인 프로세스 또는 스레드가 실행 중에 다른 프로세스에게 CPU의 제어권을 넘겨줄 수 있는 커널이다.
- 우선순위가 높은 프로세스가 ready하고 있거나 할당된 CPU사용시간이 만료되면 현재 실행중인 프로세스를 중단하고 다른 프로세스에게 CPU 자원을 넘겨준다.
- 비선점형 커널과 반대로 Race condition과 같은 동기화 문제가 발생할 가능성이 있지만 응답성과 성능이 좋기 때문에 문제가 있더라고 여러 방법을 통해 문제를 예방하면서 선점형 커널을 많이 사용한다.
CS 지식을 공부하고 기록하는 개인 공부 블로그입니다. 내용 중 틀린 부분 피드백 혹은 궁금한 점이 있으면 댓글로 남겨주시면 참고 및 답변 달아드리겠습니다🧐
'Computer Science > 운영체제' 카테고리의 다른 글
[OS/운영체제] Deadlock / 교착상태 (0) | 2024.01.27 |
---|---|
[OS/운영체제] Atomic execution과 Semaphores / Mutex (1) | 2024.01.16 |
[OS/운영체제] CPU scheduling (0) | 2024.01.01 |
[OS/운영체제] Implicit Threading / 암묵적 스레딩이란? (0) | 2023.12.31 |
[OS/운영체제] Thread / 스레드 (1) | 2023.12.22 |