2025. 2. 26. 12:24ㆍ정보기술/운영체제 (OS)
📖 1-1. 동기화(Synchronization)란?
운영체제(OS)에서 동기화(Synchronization) 는 여러 개의 프로세스 또는 스레드가 공유 자원(Shared Resource)에 안전하게 접근할 수 있도록 하는 기법입니다.
멀티태스킹 환경에서 경쟁 상태(Race Condition)와 데이터 무결성(Data Integrity) 문제를 해결하기 위해 필수적입니다.
✅ 운영체제(OS)에서 동기화란?
운영체제는 멀티태스킹(Multitasking) 기능을 지원하며, 여러 개의 프로세스 또는 스레드가 동시에 실행될 수 있는 환경을 제공합니다.
하지만, 이때 여러 스레드가 동일한 자원(변수, 파일, 메모리 등)에 접근할 경우 문제가 발생할 수 있습니다.
이를 방지하고 안전한 데이터 처리를 보장하기 위해 동기화(Synchronization) 가 필요합니다.
🔹 동기화가 필요한 주요 이유
이유 | 설명 |
경쟁 상태(Race Condition) 방지 | 여러 개의 스레드가 동시에 같은 자원에 접근할 때 예측할 수 없는 결과가 발생할 수 있음. |
데이터 무결성(Data Integrity) 유지 | 공유 데이터를 여러 스레드가 수정할 경우 데이터 손상(Data Corruption) 발생 가능. |
임계 영역(Critical Section) 보호 | 특정 코드 블록에서 한 번에 하나의 스레드만 실행되도록 보장해야 함. |
데드락(Deadlock) 방지 | 두 개 이상의 스레드가 서로의 자원을 기다리면서 무한 대기 상태에 빠지는 문제 해결. |
✅ 동기화가 필요한 이유
운영체제는 멀티스레딩(Multithreading) 환경을 제공하여 여러 작업을 동시에 수행할 수 있도록 합니다.
하지만, 적절한 동기화가 없으면 스레드 간 데이터 충돌(Data Corruption) 문제가 발생할 수 있습니다.
이를 이해하기 위해 은행 계좌 잔액 업데이트 문제를 살펴보겠습니다.
🛑 동기화가 없는 코드 예제 (문제 발생 가능)
#include <stdio.h>
#include <pthread.h>
int balance = 1000; // 공유 자원
void* withdraw(void* arg) {
balance -= 500; // 두 스레드가 동시에 실행되면 결과가 비정상적일 수 있음
return NULL;
}
int main() {
pthread_t t1, t2;
pthread_create(&t1, NULL, withdraw, NULL);
pthread_create(&t2, NULL, withdraw, NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
printf("최종 잔액: %d\n", balance); // 결과가 500이 아닐 수도 있음!
return 0;
}
📌 실행 결과 (예측 불가한 결과 발생)
최종 잔액: 500
최종 잔액: 1000
최종 잔액: 0 <-- 의도하지 않은 결과 발생 가능!
- 두 개의 스레드가 동시에 balance -= 500을 실행할 경우, 결과가 예측할 수 없는 값이 될 수 있음.
- 원하는 결과는 500이어야 하지만, 0이 될 수도 있고, 심지어 1000이 유지될 수도 있음.
- 이는 경쟁 상태(Race Condition) 때문에 발생하는 문제.
❌ 경쟁 상태(Race Condition)
경쟁 상태(Race Condition)는 두 개 이상의 스레드가 동시에 공유 자원에 접근하여, 실행 순서에 따라 예측할 수 없는 결과를 초래하는 현상입니다.
즉, 한 스레드가 데이터를 수정하는 도중에 다른 스레드가 동일한 데이터를 변경하면 데이터가 손상될 가능성이 있음.
🛑 경쟁 상태 발생 예시
- Thread 1 이 balance -= 500 연산을 수행하기 위해 balance 값을 가져옴.
- Thread 2 도 거의 동시에 balance -= 500 연산을 수행하기 위해 balance 값을 가져옴.
- 두 스레드가 연산을 수행한 후, 새로운 balance 값을 저장하는데, 이전 상태가 반영되지 않은 채 덮어씌워질 수 있음.
예제 시나리오에서 문제 가능성
- 두 개의 스레드가 동일한 값을 읽고 연산을 수행하면서 중간 연산 결과가 사라지는 문제가 발생.
- 의도한 값(500)이 나오기도 하지만, 예상치 못한 오류가 발생할 가능성이 매우 높음.
✅ 해결 방법
이러한 문제를 해결하기 위해 운영체제에서 제공하는 동기화 기법을 활용해야 합니다.
대표적인 동기화 방법은 다음과 같습니다.
기법 | 설명 |
Mutex (뮤텍스) | 한 번에 하나의 스레드만 Lock을 획득하도록 하여 경쟁 상태를 방지 |
RLock (재진입 가능 락) | 같은 스레드가 여러 번 Lock을 획득할 수 있도록 허용 |
RWLock (읽기-쓰기 락) | 여러 스레드가 동시에 읽을 수 있도록 하면서, 쓰기는 단 하나만 가능 |
Spinlock (스핀락) | Lock이 해제될 때까지 CPU가 반복해서 확인하는 방식 |
Semaphore (세마포어) | 특정 개수의 스레드만 공유 자원에 접근할 수 있도록 제한 |
✅ 뮤텍스를 활용한 동기화 해결 방법
경쟁 상태를 방지하려면 뮤텍스(Mutex, Mutual Exclusion) 를 사용하여 한 번에 하나의 스레드만 공유 자원에 접근할 수 있도록 해야 합니다.
다음 코드는 pthread_mutex_t를 사용하여 동기화 문제를 해결하는 방법을 보여줍니다.
#include <stdio.h>
#include <pthread.h>
int balance = 1000; // 공유 자원
pthread_mutex_t lock; // 뮤텍스 선언
void* withdraw(void* arg) {
pthread_mutex_lock(&lock); // 🔒 락 획득
balance -= 500;
pthread_mutex_unlock(&lock); // 🔓 락 해제
return NULL;
}
int main() {
pthread_t t1, t2;
pthread_mutex_init(&lock, NULL); // 뮤텍스 초기화
pthread_create(&t1, NULL, withdraw, NULL);
pthread_create(&t2, NULL, withdraw, NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
printf("최종 잔액: %d\n", balance); // 항상 500으로 올바르게 출력됨
pthread_mutex_destroy(&lock); // 뮤텍스 제거
return 0;
}
📌 결과
최종 잔액: 500 ✅ (예측 가능한 결과)
- 🔒 pthread_mutex_lock()을 사용하여 공유 자원 보호.
- 🔓 pthread_mutex_unlock()을 사용하여 락 해제.
- 이제 경쟁 상태 없이 안전한 동기화가 이루어짐!
✅ 정리
- 동기화(Synchronization)는 운영체제에서 여러 개의 스레드가 공유 자원에 안전하게 접근할 수 있도록 하는 필수 기법.
- 동기화가 없으면 경쟁 상태(Race Condition) 가 발생하여 데이터 무결성(Data Integrity) 이 깨질 수 있음.
- Mutex, Semaphore, Spinlock 등의 락을 사용하여 동기화를 구현할 수 있음.
'정보기술 > 운영체제 (OS)' 카테고리의 다른 글
운영체제 락 개념과 동기화 기법 (2. 기본 락(Lock) / 2-1. 뮤텍스(Mutex)) (0) | 2025.02.26 |
---|---|
운영체제 락 개념과 동기화 기법 (1. 운영체제에서 동기화 / 1-2. 임계 영역(Critical Section)과 해결 방법) (0) | 2025.02.26 |
시스템 콜 (System Call) - 6. 시스템 콜의 보안과 성능 이슈 (0) | 2025.02.08 |
시스템 콜 (System Call) - 5. 시스템 콜을 직접 사용해 보기 (0) | 2025.02.08 |
시스템 콜 (System Call) - 4. 시스템 콜이 동작하는 과정 (0) | 2025.02.08 |