Operating System(OS)에 이어서 Part2에는 다음과 같은 순서*로 알아보겠습니다.
*공룡책을 기반
[프로세스 관리]
1. 프로세스
2. 스레드와 병행성
3. CPU 스케줄링
[프로세스 동기화]
4. 프로세스동기화
5. 동기화 예제
6. 교착상태
[메모리 관리]
7. 메인 메모리
8. 가상 메모리
[저장장치 관리]
9. 대용량 저장장치 구조
10. 입출력 시스템
[파일시스템]
11. 파일시스템
12. 파일시스템 구현
Operating System(OS) Part2 - 5. 동기화 예제
1. 개요
운영체제에서 동기화는 여러 프로세스나 스레드가 공유 자원에 접근할 때 데이터의 일관성을 유지하고 경합을 방지하는 중요한 기법입니다. 동기화 문제는 병렬 프로그래밍에서 자주 발생하며, 이를 해결하지 않으면 데이터 손상, 교착 상태, 무한 대기 등의 심각한 문제가 발생할 수 있습니다. 대표적인 동기화 문제로는 유한 버퍼 문제, Reader-Writer 문제, 식사하는 철학자들 문제가 있습니다. 이 문제들은 모두 공유 자원에 대한 접근 제어를 통해 해결됩니다.
2. 유한 버퍼 문제 (The Bounded-Buffer Problem)
유한 버퍼 문제는 생산자-소비자 문제라고도 불리며, 고정 크기의 버퍼를 공유하는 두 개의 프로세스, 즉 생산자와 소비자가 존재합니다. 생산자는 버퍼에 데이터를 추가하고, 소비자는 버퍼에서 데이터를 꺼내는 역할을 합니다. 이 문제는 버퍼가 가득 찼을 때 생산자가 데이터를 추가하지 않도록 하고, 버퍼가 비었을 때 소비자가 데이터를 꺼내지 않도록 하는 것이 핵심입니다.
1) 해결 방법
- 세마포어 사용: 세마포어는 카운터를 통해 접근을 제어하는 동기화 도구입니다. 이 문제를 해결하기 위해 두 개의 세마포어 empty와 full을 사용합니다.
- empty: 버퍼의 빈 공간을 추적합니다.
- full: 버퍼에 저장된 아이템의 수를 추적합니다.
- 상호 배제 (Mutex): 버퍼에 접근하는 것을 조정하기 위해 상호 배제 세마포어 mutex를 사용합니다.
2) 코드 예제
semaphore mutex = 1; semaphore empty = N; // N은 버퍼 크기 semaphore full = 0; void producer() { while (true) { int item = produceItem(); // 아이템 생성 wait(empty); // 빈 공간이 있는지 확인 wait(mutex); // 버퍼 접근 잠금 addItemToBuffer(item); // 버퍼에 아이템 추가 signal(mutex); // 버퍼 접근 잠금 해제 signal(full); // 아이템 추가 신호 } } void consumer() { while (true) { wait(full); // 버퍼에 아이템이 있는지 확인 wait(mutex); // 버퍼 접근 잠금 int item = removeItemFromBuffer(); // 버퍼에서 아이템 제거 signal(mutex); // 버퍼 접근 잠금 해제 signal(empty); // 빈 공간 신호 consumeItem(item); // 아이템 소비 } } |
3. Reader-Writer Problem
Reader-Writer 문제는 데이터베이스와 같은 공유 자원에 대해 읽기와 쓰기 작업이 동시에 발생할 때, 데이터의 일관성을 유지하는 문제입니다. 여러 Reader가 동시에 데이터를 읽을 수 있지만, Writer는 독점적으로 자원에 접근해야 합니다.
1) 해결 방법
- 우선 순위: Reader 우선 또는 Writer 우선 방식으로 문제를 해결할 수 있습니다. 각 방식은 서로 다른 요구사항을 만족시키며 특정 시나리오에 맞게 선택할 수 있습니다.
- 세마포어 사용: 접근 제어를 위해 여러 세마포어를 사용합니다.
- rw_mutex: 공유 자원에 대한 접근을 제어합니다.
- mutex: Reader 수를 관리하는 데 사용됩니다.
- read_count: 현재 읽고 있는 Reader의 수를 저장합니다.
2) 코드 예제
semaphore rw_mutex = 1; semaphore mutex = 1; int read_count = 0; void reader() { while (true) { wait(mutex); read_count++; if (read_count == 1) wait(rw_mutex); signal(mutex); readData(); // 데이터 읽기 wait(mutex); read_count--; if (read_count == 0) signal(rw_mutex); signal(mutex); } } void writer() { while (true) { wait(rw_mutex); writeData(); // 데이터 쓰기 signal(rw_mutex); } } |
https://link.coupang.com/a/bEUFe7
* 이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받을 수 있습니다.
4. 식사하는 철학자들 문제 (The Dining-Philosophers Problem)
식사하는 철학자들 문제는 다섯 명의 철학자가 원형 테이블에 앉아 있고, 각 철학자는 왼쪽과 오른쪽에 있는 포크를 사용하여 식사를 해야 하는 상황을 묘사합니다. 철학자는 식사하거나 생각하거나 두 가지 행동만 합니다. 이 문제는 교착 상태와 경쟁 상태를 피하면서 모든 철학자가 식사할 수 있도록 하는 것이 목표입니다.
1) 해결 방법
- 상호 배제: 포크에 대한 접근을 제어하여 동시에 두 명의 철학자가 같은 포크를 사용하지 않도록 합니다.
- 세마포어 사용: 각 포크에 대해 하나의 세마포어를 사용하여 철학자가 포크를 들고 내려놓는 동작을 제어합니다.
2) 코드 예제
#define N 5 semaphore chopstick[N] = {1, 1, 1, 1, 1}; void philosopher(int i) { while (true) { think(); wait(chopstick[i]); wait(chopstick[(i+1) % N]); eat(); signal(chopstick[i]); signal(chopstick[(i+1) % N]); } } |
이 예제는 기본적인 해결 방법을 보여주지만, 교착 상태를 방지하기 위해 추가적인 조건을 적용할 수 있습니다. 예를 들어, 홀수 번호의 철학자는 왼쪽 포크부터 들고, 짝수 번호의 철학자는 오른쪽 포크부터 드는 방식으로 교착 상태를 방지할 수 있습니다.
5. 결론
동기화 문제는 운영체제에서 매우 중요한 주제이며, 적절한 동기화 기법을 통해 데이터의 일관성을 유지하고 효율적인 자원 관리를 할 수 있습니다. 유한 버퍼 문제, Reader-Writer 문제, 식사하는 철학자들 문제는 각각 다른 상황에서 발생하는 동기화 문제를 설명하며, 이를 해결하기 위한 다양한 기법들을 이해하는 것은 안정적이고 효율적인 시스템 설계를 위해 필수적입니다.
'IT Auditor Study > 운영체제' 카테고리의 다른 글
[Part2-공룡책] 6. 교착상태(2/2) - Operating System(OS) (2) | 2024.06.06 |
---|---|
[Part2-공룡책] 6. 교착상태(1/2) - Operating System(OS) (0) | 2024.06.06 |
[Part2-공룡책] 4. 프로세스 동기화 - Operating System(OS) (0) | 2024.06.06 |
[Part2-공룡책] 3. CPU 스케줄링(2/2) - Operating System(OS) (2) | 2024.06.06 |
[Part2-공룡책] 3. CPU 스케줄링(1/2) - Operating System(OS) (0) | 2024.06.06 |