STUDY

[운영체제] 프로세스 동기화: 실행 순서 제어와 상호 배제

sed 2026. 5. 27. 14:17
SMALL

프로세스 동기화

운영체제에서는 여러 프로세스가 동시에 실행된다.

 

그런데 동시에 실행되는 프로세스들은 완전히 독립적으로만 동작하지 않는다.  

때로는 서로 협력하기도 하고, 같은 자원을 함께 사용하기도 한다.

 

예를 들어 워드프로세서 프로그램을 생각해보자.

 

사용자가 글을 입력하면, 어떤 작업은 입력 내용을 화면에 출력하고, 어떤 작업은 맞춤법을 검사하고, 또 어떤 작업은 파일을 저장할 수 있다.

 

이 작업들은 동시에 수행될 수 있지만, 아무 순서로나 실행되어서는 안 된다.  

어떤 작업은 반드시 다른 작업이 끝난 뒤에 실행되어야 하고, 어떤 자원은 여러 프로세스가 동시에 접근하면 문제가 생길 수 있다.

 

그래서 필요한 개념이 `프로세스 동기화`이다.

 

참고로 동기화는 프로세스뿐만 아니라 스레드에도 적용된다.  

다만 여기서는 편의상 프로세스 동기화라고 표현하겠다.

 

동기화란?

 

동기화는 간단히 말하면 여러 프로세스가 올바르게 실행되도록 수행 시기를 맞추는 것이다.

 

운영체제에서 동기화는 크게 1. 실행 순서 제어, 2. 상호 배제 두 가지 의미로 나눌 수 있다.

 

실행 순서 제어는 프로세스들이 올바른 순서대로 실행되도록 하는 것이다.

상호 배제는 동시에 접근하면 안 되는 자원에 하나의 프로세스만 접근하도록 하는 것이다.

 

즉, 동기화는 단순히 "같은 시간에 맞춘다"는 의미가 아니라, 프로세스들이 올바른 순서와 방식으로 자원에 접근하도록 조정하는 것이라고 볼 수 있다.

 

실행 순서 제어를 위한 동기화

대표적인 예로 reader-writer 문제를 생각할 수 있다.

writer: book.txt 파일에 값을 저장하는 프로세스
reader: book.txt 파일에 저장된 값을 읽는 프로세스

 

여기서 reader와 writer는 아무 순서로나 실행되면 안 된다.

 

reader는 book.txt 파일에 값이 있어야만 정상적으로 읽을 수 있다.

그런데 writer가 아직 파일에 값을 쓰지 않았는데 reader가 먼저 실행된다면 문제가 생긴다.

 

즉, reader가 실행되기 전에 writer가 먼저 실행되어야 한다.

writer 실행
→ book.txt에 값 저장
→ reader 실행
→ book.txt의 값 읽기

 

이처럼 어떤 프로세스가 실행되기 위해 특정 조건이 먼저 만족되어야 하는 경우가 있다.

 

이때 프로세스들의 실행 순서를 맞춰주는 것이 실행 순서 제어를 위한 동기화이다.

 

상호 배제를 위한 동기화

상호 배제는 동시에 접근하면 문제가 생기는 자원에 대해, 한 번에 하나의 프로세스만 접근하도록 하는 것이다.

 

즉, 어떤 자원은 여러 프로세스가 동시에 사용하면 안 된다.

 

대표적인 예로 bank account problem를 생각해볼 수 있다.

 

현재 계좌 잔액이 10만 원이라고 하자.

 

프로세스 A는 계좌에 2만 원을 입금한다.

프로세스 A
1. 계좌 잔액을 읽는다.
2. 읽어들인 잔액에 2만 원을 더한다.
3. 더한 값을 저장한다.

 

프로세스 B는 계좌에 5만 원을 입금한다.

프로세스 B
1. 계좌 잔액을 읽는다.
2. 읽어들인 잔액에 5만 원을 더한다.
3. 더한 값을 저장한다.

 

정상적으로 실행된다면 최종 잔액은 17만 원이 되어야 한다.

 

하지만 두 프로세스가 동시에 실행되면 문제가 생길 수 있다.

예를 들어 다음과 같은 상황을 생각해보자.

1. 프로세스 A가 잔액 10만 원을 읽음
2. 문맥 교환 발생
3. 프로세스 B가 잔액 10만 원을 읽음
4. 프로세스 B가 10만 원 + 5만 원 = 15만 원 저장
5. 다시 프로세스 A 실행
6. 프로세스 A가 아까 읽어둔 10만 원 + 2만 원 = 12만 원 저장

 

이 경우 최종 잔액은 17만 원이 아니라 12만 원이 된다.

프로세스 B가 저장한 15만 원이 프로세스 A에 의해 덮어써진 것이다.

 

문제의 원인은 두 프로세스가 같은 자원, 즉 계좌 잔액에 동시에 접근했기 때문이다.

 

이처럼 동시에 접근하면 안 되는 자원에 여러 프로세스가 접근하면 데이터의 일관성이 깨질 수 있다.

 

상호 배제 문제는 생산자-소비자 문제에서도 나타난다.

 

생산자 producer는 데이터를 만들어 버퍼에 넣는 프로세스이다.

소비자 consumer는 버퍼에서 데이터를 꺼내 사용하는 프로세스이다.

 

두 프로세스가 총합이라는 변수를 공유한다고 하자.

 

생산자는 데이터를 넣을 때 총합을 1 증가시킨다.

생산자() {
    버퍼에 데이터 삽입
    총합 = 총합 + 1
}

 

소비자는 데이터를 꺼낼 때 총합을 1 감소시킨다.

소비자() {
    버퍼에서 데이터 제거
    총합 = 총합 - 1
}

 

생산자를 10만 번 실행하고, 소비자를 10만 번 실행하면 최종 총합은 0이 되어야 할 것 같다.

하지만 동기화 없이 동시에 실행하면 결과가 0이 아닐 수 있다.

 

왜냐하면 총합 = 총합 + 1이나 총합 = 총합 - 1은 한 번에 끝나는 작업처럼 보이지만, 실제로는 여러 단계로 나뉘기 때문이다.

 

예를 들어 총합 = 총합 + 1은 내부적으로 다음과 비슷하게 처리된다.

1. 총합 값을 읽는다.
2. 읽은 값에 1을 더한다.
3. 결과를 다시 총합에 저장한다.

 

이 중간에 문맥 교환이 발생하면 다른 프로세스가 같은 총합 값을 읽고 수정할 수 있다.

그 결과 총합이 엉뚱한 값이 되거나, 심하면 오류가 발생할 수도 있다.

이 역시 동기화가 되지 않았기 때문에 발생하는 문제이다.

 

 

공유 자원(Shared Resource)

공유 자원(shared resource)은 여러 프로세스나 스레드가 함께 사용하는 자원이다.

예를 들어 전역 변수, 파일, 입출력 장치, 보조기억장치, 공유 메모리 같은 것들이 공유 자원이 될 수 있다.

 

공유 자원이라고 해서 항상 문제가 생기는 것은 아니다.

문제는 동시에 접근했을 때 값이 꼬이거나 일관성이 깨질 수 있는 자원이다.

 

예를 들어 단순히 읽기만 하는 데이터라면 여러 프로세스가 동시에 읽어도 큰 문제가 없을 수 있다.

하지만 값을 수정하는 자원이라면 동시에 접근했을 때 문제가 발생할 수 있다.

 

은행 계좌의 잔액 변수, 생산자-소비자 문제의 총합 변수 같은 것이 대표적인 예이다.

임계 구역(Critical Section)

임계 구역(critical section)은 동시에 실행하면 문제가 발생할 수 있는 코드 영역이다.

즉, 공유 자원에 접근하는 코드 중에서도 특히 동시에 실행되면 안 되는 부분을 말한다.

 

예를 들어 은행 계좌 문제에서는 다음 코드가 임계 구역이다.

계좌 잔액을 읽는다.
잔액에 금액을 더한다.
변경된 잔액을 저장한다.

 

생산자-소비자 문제에서는 다음 코드가 임계 구역이다.

총합 = 총합 + 1
총합 = 총합 - 1

 

이 코드들은 여러 프로세스가 동시에 실행하면 값이 꼬일 수 있다.

 

따라서 한 프로세스가 임계 구역에 들어가 있으면, 다른 프로세스는 그 임계 구역에 들어가면 안 된다.

 

 

『혼자 공부하는 컴퓨터 구조+운영체제』의 책 내용

레이스 컨디션

임계 구역에 여러 프로세스가 동시에 접근하면 자원의 일관성이 깨질 수 있다.

이런 상황을 레이스 컨디션(race condition)이라고 한다.

레이스 컨디션은 여러 프로세스나 스레드가 동시에 공유 자원에 접근하고, 실행 순서에 따라 결과가 달라지는 문제이다.

 

은행 계좌 문제를 다시 보면, 최종 잔액이 17만 원이 되어야 하지만 실행 순서에 따라 12만 원이나 15만 원이 될 수도 있다.

즉, 결과가 일정하지 않다.

이처럼 실행 순서에 따라 결과가 달라지는 것이 레이스 컨디션이다.

 

임계 구역 문제 해결 원칙

운영체제는 임계 구역 문제를 해결하기 위해 세 가지 원칙을 만족해야 한다.

1. 상호 배제

상호 배제(mutual exclusion)는 한 프로세스가 임계 구역에 진입했다면, 다른 프로세스는 동시에 임계 구역에 들어갈 수 없다는 원칙이다.

이 원칙이 지켜지지 않으면 여러 프로세스가 동시에 공유 자원을 수정할 수 있고, 데이터의 일관성이 깨질 수 있다.

즉, 상호 배제는 임계 구역 문제 해결의 가장 기본 조건이다.

2. 진행

진행(progress)은 임계 구역에 어떤 프로세스도 들어가 있지 않다면, 임계 구역에 들어가고자 하는 프로세스는 들어갈 수 있어야 한다는 원칙이다.

쉽게 말해, 아무도 임계 구역을 사용하지 않고 있는데도 모든 프로세스가 계속 기다리기만 하면 안 된다는 뜻이다.

진행 조건이 없다면 임계 구역이 비어 있는데도 프로세스들이 계속 대기하는 비효율적인 상황이 생길 수 있다.

3. 유한 대기

유한 대기(bounded waiting)는 어떤 프로세스가 임계 구역에 들어가고 싶어 한다면, 언젠가는 반드시 들어갈 수 있어야 한다는 원칙이다.

즉, 무한정 기다리면 안 된다.

만약 어떤 프로세스가 계속 밀려서 임계 구역에 들어가지 못한다면 기아 현상이 발생한다.

 

유한 대기는 이런 상황을 막기 위한 조건이다.

LIST