4. 동기화와 교착상태

규미·2025년 9월 28일

CS-study

목록 보기
4/10

4. 동기화와 교착상태

컴퓨터에 여러 프로세스(또는 스레드)가 동시에 실행될 때, 이들이 공유된 자원(Shared Resource), 예를 들어 같은 메모리 변수나 파일에 접근하려고 하면 문제가 발생할 수 있습니다. 동기화(Synchronization)는 이러한 문제들을 해결하고 작업 순서를 조율하여 데이터의 일관성을 유지하는 기술이며, 교착상태(Deadlock)는 동기화 과정에서 발생할 수 있는 최악의 부작용입니다.

Critical Section 문제 (임계 구역 문제)

💬 개념

  • *임계 구역(Critical Section)이란, 둘 이상의 프로세스가 동시에 접근하면 안 되는 공유 자원에 접근하는 코드 영역**을 말합니다.

임계 구역 문제는 이러한 임계 구역에 여러 프로세스가 동시에 진입하지 못하도록 막는, 즉 상호 배제(Mutual Exclusion)를 보장하는 프로토콜을 설계하는 문제입니다.

  • 경쟁 상태 (Race Condition): 여러 프로세스가 동시에 임계 구역에 진입하여 공유 데이터를 조작한 결과, 최종 결과가 예측 불가능하게 틀어지는 상황을 말합니다.

🚽 쉬운 비유: 1인용 화장실

임계 구역 문제는 '1인용 화장실'에 여러 사람이 동시에 들어가려는 상황과 같습니다.

  • 공유 자원: 화장실
  • 임계 구역: 화장실 안에서 용무를 보는 행위
  • 경쟁 상태: 여러 사람이 동시에 문을 열고 들어가려 해 아수라장이 되는 상황
  • 해결책: 화장실 문에 '잠금장치'를 다는 것. 이것이 바로 동기화 메커니즘입니다.

⚙️ 해결책의 조건

임계 구역 문제를 해결하기 위한 알고리즘은 아래 세 가지 조건을 반드시 만족해야 합니다.

  1. 상호 배제 (Mutual Exclusion): 한 프로세스가 임계 구역에 있으면, 다른 프로세스는 들어올 수 없다. (한 사람이 화장실에 있으면 다른 사람은 못 들어간다.)
  2. 진행 (Progress): 임계 구역에 아무도 없고, 들어가려는 프로세스가 있다면 반드시 하나는 들어갈 수 있어야 한다. (화장실이 비어있고 기다리는 사람이 있으면, 반드시 한 명은 들어갈 수 있어야 한다.)
  3. 한정된 대기 (Bounded Waiting): 어떤 프로세스라도 임계 구역에 들어가기 위해 무한정 기다려서는 안 된다. (모든 사람은 언젠가 화장실에 들어갈 수 있어야 한다.)

뮤텍스, 세마포어, 모니터

위에서 말한 '잠금장치'를 구현하는 대표적인 동기화 도구들입니다.

1. 뮤텍스 (Mutex)

Mutual Exclusion의 약자로, 이름 그대로 상호 배제를 위한 가장 기본적인 도구입니다. 오직 하나의 스레드만 임계 구역에 들어갈 수 있도록 합니다.

  • 동작: 스레드가 임계 구역에 들어가기 전 lock()*을 걸고, 나올 때 unlock()*을 합니다. 다른 스레드가 lock()을 시도하면 이미 잠겨있으므로 대기하게 됩니다.
  • 특징: lock()을 건 스레드만이 unlock()을 할 수 있습니다.
  • 비유: 화장실 열쇠 🔑. 열쇠를 가진 사람(lock을 건 스레드)만이 문을 잠그고 들어갈 수 있으며, 나올 때도 반드시 자신이 가진 그 열쇠로 문을 열어야(unlock) 합니다.

2. 세마포어 (Semaphore)

뮤텍스가 '1개의 자원'에 대한 잠금이라면, 세마포어는 '여러 개의 자원'에 대한 접근을 제어할 수 있는 더 일반적인 도구입니다.

  • 동작: 세마포어는 가용 자원의 개수를 나타내는 정수 값(Counter)을 가집니다. wait() 연산은 자원을 획득(카운터 감소)하고, signal() 연산은 자원을 반납(카운터 증가)합니다. 카운터가 0일 때 wait()를 시도하면 대기합니다.
  • 특징: wait()를 한 스레드와 signal()을 하는 스레드가 달라도 됩니다. 뮤텍스는 카운터가 1인 '바이너리 세마포어(Binary Semaphore)'로 볼 수 있습니다.
  • 비유: 스터디 카페의 5개짜리 룸 열쇠 꾸러미 🗝️🗝️🗝️🗝️🗝️.
    • 카운터 = 5 (사용 가능한 룸 5개)
    • 학생이 룸을 쓰려면(wait()), 데스크에서 열쇠를 하나 받아갑니다. (카운터 4)
    • 룸 사용이 끝나면(signal()), 열쇠를 반납합니다. (카운터 5)
    • 열쇠가 하나도 없으면(카운터 0) 다른 학생이 열쇠를 반납할 때까지 기다려야 합니다.

3. 모니터 (Monitor)

뮤텍스와 세마포어는 개발자가 lock(), unlock() 등을 직접 호출해야 하므로 실수하기 쉽습니다. (예: unlock()을 깜빡하는 경우) 모니터는 이러한 위험을 줄이기 위해 프로그래밍 언어 차원에서 제공하는 고수준 동기화 구조입니다.

  • 동작: 공유 자원과 그 자원에 접근하는 함수들을 하나의 '객체'처럼 캡슐화합니다. 개발자는 그냥 모니터 안의 함수를 호출하기만 하면, 컴파일러가 알아서 상호 배제를 위한 코드를 추가해 줍니다.
  • 특징: 사용하기 매우 편리하고 안전합니다. Java의 synchronized 키워드가 대표적인 모니터 구현입니다.
  • 비유: 자동 잠금 화장실. 사람이 들어가면 문이 자동으로 잠기고, 나오면 자동으로 열립니다. 사용자는 열쇠에 대해 전혀 신경 쓸 필요 없이 문을 사용하기만 하면 됩니다.

Deadlock (교착 상태)

교착 상태란, 둘 이상의 프로세스가 서로가 가진 자원을 기다리며 무한히 대기하는 상태를 말합니다. 모든 프로세스가 멈춰버려 시스템이 마비될 수 있습니다.

🚗 쉬운 비유: 좁은 골목길의 두 자동차

일방통행만 가능한 좁은 골목길 양쪽에서 차가 동시에 진입한 상황입니다. 두 차는 서로가 비켜주기만을 기다리며 한 발짝도 움직이지 못합니다. 이것이 바로 교착 상태입니다.

📌 Deadlock 발생 4대 조건

아래 4가지 조건이 모두 충족될 때만 교착 상태가 발생할 수 있습니다. 하나라도 깨지면 교착 상태는 일어나지 않습니다.

  1. 상호 배제 (Mutual Exclusion): 자원은 한 번에 한 프로세스만 사용할 수 있다. (골목길은 한 번에 한 대만 지나갈 수 있다.)
  2. 점유와 대기 (Hold and Wait): 프로세스가 최소 하나의 자원을 점유한 채로, 다른 프로세스가 점유한 자원을 추가로 기다린다. (차가 골목길 중간을 차지한 채로, 상대방 차가 비켜주기를 기다린다.)
  3. 비선점 (No Preemption): 다른 프로세스가 사용 중인 자원을 강제로 빼앗을 수 없다. (상대방 차를 강제로 후진시킬 수 없다.)
  4. 환형 대기 (Circular Wait): 자원을 기다리는 프로세스들이 원형으로 연결되어 있다. (A차는 B차가 비키길 기다리고, B차는 A차가 비키길 기다린다.)

🛠️ Deadlock 해결 방법

  1. 예방 (Prevention): 교착 상태 발생 4대 조건 중 하나 이상을 깨뜨리는 방법입니다. 가장 강력하지만 자원 낭비나 시스템 비효율을 초래할 수 있습니다.
    • 환형 대기 방지: 모든 자원에 고유 번호를 부여하고, 번호 순서대로만 자원을 요청하도록 강제합니다.
  2. 회피 (Avoidance): 프로세스가 자원을 요청할 때, 이 요청을 수락하면 미래에 교착 상태가 발생할 가능성이 있는지 미리 검사(시뮬레이션)하는 방법입니다. 교착 상태를 유발할 가능성이 있다면 요청을 보류합니다. 은행원 알고리즘(Banker's Algorithm)이 대표적입니다.
  3. 탐지 및 회복 (Detection & Recovery): 교착 상태가 발생하는 것을 허용한 뒤, 주기적으로 시스템을 검사하여 교착 상태를 찾아내고 해결하는 방법입니다.
    • 탐지: 자원 할당 그래프 등을 사용하여 교착 상태를 탐지합니다.
    • 회복: 교착 상태에 빠진 프로세스 중 일부를 강제 종료하거나, 자원을 빼앗아 다른 프로세스에 할당합니다.
  4. 무시 (Ignorance): 교착 상태는 매우 드물게 발생한다고 가정하고, 그냥 아무런 조치도 취하지 않는 방법입니다. 만약 교착 상태가 발생하면 사용자가 직접 프로세스를 종료하거나 시스템을 재부팅하도록 합니다. 대부분의 범용 운영체제(Windows, macOS 등)가 이 방식을 사용합니다.

5개의 댓글

comment-user-thumbnail
2025년 9월 28일

비유가 있어서 이해하기 좋았어요!

답글 달기
comment-user-thumbnail
2025년 9월 28일

비유를 추가해서 설명해주셔서 이해하기 훨씬 쉬웠어요

답글 달기
comment-user-thumbnail
2025년 9월 29일

간결하고 이해하기 쉬운 글이네요! 잘 읽었습니당

답글 달기
comment-user-thumbnail
2025년 9월 29일

이모티콘과 예시가 있어서 읽기 좋았습니다!

답글 달기
comment-user-thumbnail
2025년 9월 29일

쉬운 비유 재밌네요 다음에도 해주세용

답글 달기