🤖

본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.

⚠️

본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.

이미지 로딩 중...

프로세스 동기화 완벽 가이드 - 슬라이드 1/7
A

AI Generated

2025. 12. 28. · 2 Views

프로세스 동기화 완벽 가이드

멀티스레드 환경에서 여러 프로세스가 공유 자원에 안전하게 접근하는 방법을 알아봅니다. Race Condition부터 Peterson 알고리즘까지 동기화의 핵심 개념을 실무 예제와 함께 쉽게 설명합니다.


목차

  1. Race_Condition이란
  2. 임계_영역
  3. 상호_배제
  4. 진행_조건
  5. 한정_대기
  6. Peterson_알고리즘

1. Race Condition이란

어느 날 김개발 씨가 은행 계좌 시스템을 개발하고 있었습니다. 테스트를 돌려보니 이상한 일이 벌어졌습니다.

분명히 10만 원을 입금했는데, 잔액이 5만 원만 늘어난 것입니다. "분명히 코드는 맞는데..." 김개발 씨는 고개를 갸웃거렸습니다.

Race Condition은 두 개 이상의 프로세스나 스레드가 공유 자원에 동시에 접근할 때 실행 순서에 따라 결과가 달라지는 현상입니다. 마치 두 사람이 동시에 같은 문을 열려고 할 때 누가 먼저 손잡이를 잡느냐에 따라 결과가 달라지는 것과 같습니다.

이 문제를 이해하면 왜 동기화가 필수인지 깨닫게 됩니다.

다음 코드를 살펴봅시다.

// 공유 자원: 은행 계좌 잔액
int balance = 100000;

// 스레드 A: 입금 작업
void deposit(int amount) {
    int temp = balance;      // 1. 현재 잔액 읽기
    temp = temp + amount;    // 2. 금액 더하기
    balance = temp;          // 3. 잔액 저장
}

// 스레드 B: 동시에 입금 실행
// A와 B가 동시에 실행되면?
// A: temp = 100000
// B: temp = 100000  (A가 저장하기 전에 읽음)
// A: balance = 150000
// B: balance = 150000  (A의 결과를 덮어씀!)

김개발 씨는 입사 6개월 차 주니어 개발자입니다. 오늘은 은행 계좌 시스템의 입금 기능을 구현하는 중이었습니다.

코드는 간단해 보였습니다. 현재 잔액을 읽고, 입금액을 더하고, 다시 저장하면 끝이니까요.

그런데 부하 테스트를 돌리자 이상한 일이 벌어졌습니다. 100명이 동시에 1만 원씩 입금했는데, 잔액이 100만 원이 아니라 50만 원만 늘어난 것입니다.

김개발 씨는 멘붕에 빠졌습니다. 선배 개발자 박시니어 씨가 다가와 상황을 살펴봤습니다.

"아, 전형적인 Race Condition이네요. 동시성 프로그래밍에서 가장 흔하게 만나는 함정이에요." 그렇다면 Race Condition이란 정확히 무엇일까요?

쉽게 비유하자면, Race Condition은 마치 마라톤 결승선에서 벌어지는 상황과 같습니다. 두 선수가 거의 동시에 들어오면 누가 1등인지 판정하기 어렵습니다.

사진 판독을 해야 하고, 때로는 논란이 되기도 합니다. 컴퓨터에서도 마찬가지입니다.

두 스레드가 거의 동시에 같은 데이터를 건드리면, 누구의 작업이 최종 결과에 반영될지 알 수 없습니다. 문제는 이 상황이 항상 발생하는 게 아니라는 점입니다.

개발 환경에서는 멀쩡히 돌아가다가 실서버에 배포하면 갑자기 터지기도 합니다. CPU의 스케줄링이 매번 조금씩 다르기 때문입니다.

위 코드를 자세히 살펴보겠습니다. deposit 함수는 세 단계로 나뉩니다.

먼저 현재 잔액을 temp 변수에 읽어옵니다. 그 다음 입금액을 더합니다.

마지막으로 결과를 다시 저장합니다. 문제는 이 세 단계가 원자적으로 실행되지 않는다는 것입니다.

스레드 A가 1단계를 실행한 직후, CPU가 스레드 B로 전환될 수 있습니다. 그러면 스레드 B도 아직 변경되지 않은 잔액을 읽게 됩니다.

실제 현업에서는 어떻게 이 문제를 겪게 될까요? 쇼핑몰의 재고 관리가 대표적입니다.

인기 상품 10개가 남았는데 100명이 동시에 주문 버튼을 누르면 어떻게 될까요? Race Condition이 발생하면 재고가 마이너스가 되거나, 20명에게 주문 완료 메시지가 가는 참사가 벌어집니다.

항공권 예약 시스템도 마찬가지입니다. 같은 좌석을 두 사람이 동시에 예약하는 상황을 막지 못하면, 비행기에서 자리 싸움이 벌어질 수도 있습니다.

박시니어 씨가 말을 이었습니다. "Race Condition을 막으려면 동기화가 필요해요.

다음에 알려줄 임계 영역상호 배제 개념을 잘 기억해 두세요." 김개발 씨는 고개를 끄덕였습니다. 단순해 보이는 코드 뒤에 이런 함정이 숨어 있다니, 동시성 프로그래밍이 어렵다는 말이 괜히 나온 게 아니었습니다.

실전 팁

💡 - Race Condition은 재현이 어렵습니다. 로그를 충분히 남기고 부하 테스트를 반복하세요.

  • 공유 자원에 접근하는 코드를 발견하면 반드시 동기화 여부를 확인하세요.

2. 임계 영역

Race Condition의 존재를 알게 된 김개발 씨는 새로운 의문이 생겼습니다. "모든 코드를 보호해야 하나요?" 박시니어 씨는 웃으며 대답했습니다.

"아니요, 정말 중요한 부분만 보호하면 돼요. 그게 바로 임계 영역이에요."

**임계 영역(Critical Section)**은 공유 자원에 접근하는 코드 영역을 말합니다. 마치 은행 금고처럼 한 번에 한 사람만 들어갈 수 있어야 하는 구역입니다.

임계 영역을 정확히 식별하면 최소한의 동기화로 최대의 성능을 얻을 수 있습니다.

다음 코드를 살펴봅시다.

public class BankAccount {
    private int balance = 0;

    public void transfer(int amount) {
        // 비임계 영역: 로그 기록 (각자 해도 됨)
        log("Transfer started");

        // === 임계 영역 시작 ===
        int current = this.balance;
        current = current + amount;
        this.balance = current;
        // === 임계 영역 끝 ===

        // 비임계 영역: 알림 발송
        sendNotification();
    }
}

김개발 씨는 Race Condition을 이해하고 나니 조금 걱정이 됐습니다. "그러면 모든 코드에 동기화를 걸어야 하나요?

그러면 성능이 엄청 떨어지지 않을까요?" 박시니어 씨가 고개를 저었습니다. "좋은 질문이에요.

모든 코드를 보호할 필요는 없어요. 공유 자원을 건드리는 핵심 부분만 보호하면 됩니다.

그 부분을 임계 영역이라고 불러요." 임계 영역을 이해하기 위해 은행 금고를 상상해 봅시다. 은행에서 돈을 넣고 빼는 작업은 금고 안에서 이루어집니다.

금고 문은 한 번에 한 사람만 들어갈 수 있도록 설계되어 있습니다. 하지만 창구에서 서류를 작성하거나 번호표를 뽑는 것은 여러 사람이 동시에 해도 됩니다.

프로그램도 마찬가지입니다. 공유 변수를 읽고 쓰는 부분만 임계 영역입니다.

로그를 남기거나, 알림을 보내거나, 단순히 계산하는 부분은 임계 영역이 아닙니다. 위 코드를 보면 transfer 메서드 전체가 아니라 balance를 다루는 세 줄만 임계 영역입니다.

로그 기록과 알림 발송은 각 스레드가 독립적으로 수행해도 문제없습니다. 임계 영역을 정확히 식별하는 것이 왜 중요할까요?

동기화에는 비용이 따르기 때문입니다. 동기화를 걸면 한 스레드가 임계 영역에 들어갈 때 다른 스레드들은 기다려야 합니다.

임계 영역이 너무 넓으면 병목이 생깁니다. 마치 은행 금고 안에서 서류 작성까지 하면 다른 손님들이 한참을 기다려야 하는 것과 같습니다.

반대로 임계 영역을 너무 좁게 잡으면 어떨까요? 보호해야 할 코드가 보호되지 않아 Race Condition이 발생합니다.

균형을 잡는 것이 중요합니다. 실무에서 임계 영역을 찾는 팁을 알려드리겠습니다.

코드에서 공유 변수를 찾으세요. 그 변수를 읽거나 쓰는 부분을 표시하세요.

읽고 쓰는 작업이 한 묶음으로 이루어져야 하는지 확인하세요. 한 묶음이어야 한다면, 그 전체가 임계 영역입니다.

김개발 씨가 물었습니다. "그러면 임계 영역을 어떻게 보호하나요?" 박시니어 씨가 대답했습니다.

"그게 바로 다음에 배울 상호 배제 개념이에요. 임계 영역에는 한 번에 하나만 들어갈 수 있도록 만드는 거죠." 김개발 씨는 서서히 동기화의 전체 그림이 그려지기 시작했습니다.

실전 팁

💡 - 임계 영역은 최대한 작게 유지하세요. 성능에 직접적인 영향을 미칩니다.

  • 공유 자원을 식별할 때는 인스턴스 변수, 전역 변수, 파일, 데이터베이스를 모두 고려하세요.

3. 상호 배제

김개발 씨는 임계 영역이 무엇인지 이해했습니다. 이제 문제는 어떻게 한 번에 하나의 스레드만 임계 영역에 들어가게 할 것인가였습니다.

박시니어 씨가 화이트보드에 그림을 그리기 시작했습니다. "자, 이제 상호 배제에 대해 알아볼까요?"

**상호 배제(Mutual Exclusion)**는 한 프로세스가 임계 영역에서 실행 중일 때 다른 프로세스는 절대 진입할 수 없도록 보장하는 원칙입니다. 마치 화장실 문을 잠그면 다른 사람이 들어올 수 없는 것과 같습니다.

이것은 동기화의 가장 기본이 되는 조건입니다.

다음 코드를 살펴봅시다.

public class MutualExclusionExample {
    private boolean isLocked = false;

    public void enterCriticalSection() {
        // 잠금 획득 시도
        while (isLocked) {
            // 다른 스레드가 사용 중이면 대기
            Thread.yield();
        }
        isLocked = true;  // 잠금 획득

        // === 임계 영역 ===
        // 공유 자원 접근 코드
        // ================

        isLocked = false;  // 잠금 해제
    }
}
// 주의: 이 코드는 개념 설명용이며 실제로는 Race Condition 존재

박시니어 씨가 화이트보드에 화장실 그림을 그렸습니다. "상호 배제를 이해하는 가장 쉬운 방법은 화장실을 생각하는 거예요." 화장실에는 잠금장치가 있습니다.

누군가 안에 들어가면 문을 잠급니다. 다른 사람이 와서 문을 열려고 하면, 잠겨 있으니 기다려야 합니다.

안에 있던 사람이 나오면서 잠금을 풀면, 그제야 다음 사람이 들어갈 수 있습니다. 상호 배제도 정확히 같은 원리입니다.

임계 영역에 들어갈 때 잠금을 획득하고, 나올 때 잠금을 해제합니다. 잠금이 걸려 있으면 다른 스레드는 기다려야 합니다.

위 코드를 보면 isLocked라는 변수가 잠금 역할을 합니다. 임계 영역에 들어가기 전에 while 루프로 잠금 상태를 확인합니다.

이미 잠겨 있으면 계속 기다립니다. 잠금이 풀리면 자신이 잠그고 들어갑니다.

그런데 박시니어 씨가 중요한 점을 지적했습니다. "이 코드에도 사실 문제가 있어요.

알아채셨나요?" 김개발 씨가 코드를 자세히 들여다봤습니다. 아, while 루프를 빠져나온 직후, isLocked를 true로 설정하기 직전에 다른 스레드가 끼어들 수 있습니다.

그러면 두 스레드가 동시에 임계 영역에 들어가는 상황이 발생합니다. 이것이 바로 상호 배제를 제대로 구현하는 것이 어려운 이유입니다.

잠금 확인과 잠금 획득이 원자적으로 이루어져야 합니다. 그래서 운영체제나 하드웨어 수준에서 이를 지원하는 특별한 명령어를 제공합니다.

Java에서는 synchronized 키워드나 Lock 인터페이스를 사용합니다. 이들은 내부적으로 원자적 연산을 사용하여 상호 배제를 보장합니다.

실무에서 상호 배제가 깨지면 어떤 일이 벌어질까요? 앞서 본 은행 잔액 문제가 대표적입니다.

더 심각한 경우, 데이터가 완전히 깨져버릴 수도 있습니다. 예를 들어 파일을 쓰는 도중에 다른 스레드가 끼어들면 파일이 손상됩니다.

김개발 씨가 고개를 끄덕였습니다. "상호 배제가 중요하다는 건 알겠어요.

그런데 상호 배제만 있으면 충분한가요?" 박시니어 씨가 미소를 지었습니다. "좋은 질문이에요.

상호 배제만으로는 부족해요. 진행 조건한정 대기라는 두 가지 조건이 더 필요하답니다."

실전 팁

💡 - 직접 상호 배제를 구현하지 마세요. 언어나 프레임워크에서 제공하는 동기화 도구를 사용하세요.

  • Java의 synchronized, Python의 Lock, Go의 Mutex 등을 활용하세요.

4. 진행 조건

상호 배제를 배운 김개발 씨는 뿌듯했습니다. 그런데 박시니어 씨가 새로운 문제를 던졌습니다.

"만약 아무도 임계 영역에 없는데도 아무도 못 들어간다면요?" 김개발 씨는 잠시 생각에 잠겼습니다. 그런 상황이 가능할까요?

진행(Progress) 조건은 임계 영역이 비어 있을 때, 들어가고자 하는 프로세스가 있다면 반드시 그 중 하나가 선택되어 진입할 수 있어야 한다는 원칙입니다. 마치 빈 화장실 앞에서 서로 양보만 하다가 아무도 못 들어가는 상황을 막아야 하는 것과 같습니다.

다음 코드를 살펴봅시다.

public class ProgressViolation {
    private int turn = 0;  // 0: A 차례, 1: B 차례

    // 스레드 A
    public void processA() {
        while (turn != 0) {
            // A 차례가 아니면 대기
        }
        // 임계 영역
        criticalSection();
        turn = 1;  // B에게 양보
    }

    // 문제: A만 사용하고 싶어도 B가 한 번은 실행되어야 함
    // B가 종료되면 A는 영원히 대기하게 됨
    // -> 진행 조건 위반!
}

박시니어 씨가 재미있는 상황을 예로 들었습니다. "한국식 양보 문화를 생각해 보세요.

엘리베이터 앞에서 '먼저 타세요', '아니요, 먼저 타세요' 하다가 문이 닫혀버리는 경우 있잖아요?" 이것이 바로 진행 조건 위반입니다. 아무도 엘리베이터를 사용하고 있지 않은데, 서로 양보하느라 아무도 못 타는 상황입니다.

위 코드를 보면 turn 변수를 사용해서 차례를 정합니다. A가 임계 영역을 사용한 후에는 반드시 B에게 차례를 넘깁니다.

언뜻 보면 공평해 보입니다. 하지만 문제가 있습니다.

A가 임계 영역을 10번 연속으로 사용하고 싶다고 가정해 봅시다. A는 한 번 사용한 후 turn을 1로 바꿉니다.

이제 A는 B가 실행될 때까지 기다려야 합니다. B가 임계 영역을 사용할 일이 없어도, A를 위해 한 번은 실행되어야 합니다.

더 심각한 상황도 있습니다. B 스레드가 종료되어 버리면 어떻게 될까요?

A는 영원히 자신의 차례가 오기를 기다리게 됩니다. 임계 영역이 텅 비어 있는데도 말이죠.

이런 상황을 **교착 상태(Deadlock)**의 변형이라고 볼 수 있습니다. 자원은 사용 가능한데 진입하지 못하는 것입니다.

올바른 동기화 알고리즘은 다음을 보장해야 합니다. 임계 영역이 비어 있고, 진입을 원하는 프로세스가 있다면, 반드시 그 중 하나는 유한한 시간 내에 진입할 수 있어야 합니다.

진행 조건이 왜 중요할까요? 시스템의 **처리량(Throughput)**과 직결되기 때문입니다.

자원이 놀고 있는데 작업이 진행되지 않으면 비효율적입니다. 특히 서버 시스템에서는 이런 비효율이 곧 비용 증가로 이어집니다.

김개발 씨가 물었습니다. "그러면 turn 방식 대신 어떻게 해야 하나요?" 박시니어 씨가 대답했습니다.

"각 스레드가 자신의 의향을 표시하는 방식을 써야 해요. '나 들어가고 싶어요'라는 플래그를 두는 거죠.

그러면 상대방이 관심 없을 때 바로 들어갈 수 있어요. 이건 Peterson 알고리즘에서 자세히 다룰 거예요." 김개발 씨는 동기화가 단순히 잠금만 거는 게 아니라, 여러 조건을 균형 있게 만족시켜야 한다는 것을 깨달았습니다.

실전 팁

💡 - 진행 조건을 검증할 때는 한 프로세스만 동작하는 시나리오도 테스트하세요.

  • 의존 관계가 있는 스레드가 종료될 때의 동작을 반드시 고려하세요.

5. 한정 대기

김개발 씨는 상호 배제와 진행 조건을 이해했습니다. "이제 완벽한 동기화를 만들 수 있겠네요!" 하지만 박시니어 씨가 손을 저었습니다.

"아직 하나 더 있어요. 영원히 기다리는 스레드가 생기면 안 되거든요."

**한정 대기(Bounded Waiting)**는 어떤 프로세스가 임계 영역에 진입 요청을 한 후, 다른 프로세스들이 임계 영역에 진입하는 횟수에 한계가 있어야 한다는 조건입니다. 마치 병원에서 번호표를 받으면 언젠가는 반드시 진료를 받을 수 있다는 보장과 같습니다.

이것이 없으면 기아(Starvation) 상태가 발생합니다.

다음 코드를 살펴봅시다.

public class StarvationExample {
    private Lock lock = new ReentrantLock();

    public void process() {
        lock.lock();  // 잠금 획득 시도
        try {
            // 임계 영역
            doWork();
        } finally {
            lock.unlock();
        }
    }

    // 문제 시나리오:
    // 스레드 A, B, C가 대기 중일 때
    // A가 해제 -> B가 획득 -> B가 해제 -> A가 또 획득
    // C는 계속 기다림 (기아 상태)
    //
    // 해결: ReentrantLock(true)로 공정 모드 사용
}

박시니어 씨가 점심시간에 있었던 일을 이야기했습니다. "오늘 구내식당에서 줄을 섰는데, 뒤에 오는 사람들이 자꾸 새치기를 하는 거예요.

한 시간을 기다렸는데 제 차례가 안 오더라고요." 이것이 바로 기아(Starvation) 상태입니다. 한정 대기 조건이 지켜지지 않으면 발생하는 문제입니다.

한정 대기란 무엇일까요? 임계 영역에 진입을 요청한 프로세스는 유한한 시간 내에 반드시 진입할 수 있어야 합니다.

다른 프로세스가 먼저 진입하는 횟수에 상한선이 있어야 한다는 뜻입니다. 병원의 번호표 시스템을 생각해 보세요.

번호표를 받으면 언젠가는 반드시 진료를 받습니다. 나중에 온 사람이 먼저 진료받는 일은 없습니다.

이것이 **공정성(Fairness)**입니다. 위 코드는 Java의 ReentrantLock을 사용합니다.

기본 설정에서는 잠금이 해제될 때 어떤 대기 스레드가 획득할지 보장하지 않습니다. 운이 좋은 스레드가 계속 획득하고, 운이 나쁜 스레드는 영원히 기다릴 수 있습니다.

해결책은 **공정 잠금(Fair Lock)**을 사용하는 것입니다. ReentrantLock의 생성자에 true를 전달하면 공정 모드가 활성화됩니다.

이 모드에서는 먼저 대기한 스레드가 먼저 획득합니다. 선입선출(FIFO) 방식입니다.

하지만 공정 잠금에는 대가가 따릅니다. 성능이 떨어집니다.

매번 대기열을 관리하고 순서를 확인해야 하기 때문입니다. 그래서 기아 상태가 문제되는 상황에서만 사용하는 것이 좋습니다.

실무에서 기아 상태가 발생하는 대표적인 사례가 있습니다. 웹 서버에서 특정 요청이 계속 뒤로 밀리는 경우입니다.

급한 요청을 먼저 처리하다 보면 일반 요청이 무한정 대기할 수 있습니다. 이를 막기 위해 에이징(Aging) 기법을 사용합니다.

오래 기다린 요청의 우선순위를 점점 높이는 것입니다. 김개발 씨가 정리했습니다.

"상호 배제, 진행, 한정 대기. 이 세 가지가 동기화의 필수 조건이군요." 박시니어 씨가 고개를 끄덕였습니다.

"맞아요. 이 세 조건을 모두 만족하는 알고리즘을 만드는 것이 동기화의 핵심이에요.

다음에 배울 Peterson 알고리즘이 이 세 조건을 어떻게 만족하는지 살펴볼 거예요."

실전 팁

💡 - 대기 시간이 긴 작업에는 공정 잠금 사용을 고려하세요.

  • 우선순위 기반 시스템에서는 에이징 기법으로 기아 상태를 방지하세요.

6. Peterson 알고리즘

드디어 마지막 주제입니다. 박시니어 씨가 칠판에 알고리즘을 적기 시작했습니다.

"지금까지 배운 세 가지 조건을 모두 만족하는 고전적인 알고리즘이 있어요. 1981년에 Gary Peterson이라는 분이 고안했죠.

이게 바로 Peterson 알고리즘이에요."

Peterson 알고리즘은 두 개의 프로세스 간에 상호 배제, 진행, 한정 대기를 모두 만족하는 동기화 알고리즘입니다. 마치 두 사람이 좁은 문을 통과할 때 깃발과 차례판을 사용해서 충돌 없이 질서 있게 지나가는 방법과 같습니다.

소프트웨어만으로 동기화를 구현하는 대표적인 알고리즘입니다.

다음 코드를 살펴봅시다.

public class PetersonAlgorithm {
    private boolean[] flag = new boolean[2];  // 진입 의사
    private int turn;  // 양보할 차례

    public void enterCriticalSection(int id) {
        int other = 1 - id;  // 상대방 ID

        flag[id] = true;    // 1. 나 들어가고 싶어요
        turn = other;       // 2. 근데 양보할게요

        // 3. 상대방도 원하고, 상대방 차례면 대기
        while (flag[other] && turn == other) {
            Thread.yield();
        }

        // === 임계 영역 ===
        criticalSection();
        // ================

        flag[id] = false;   // 4. 나 다 썼어요
    }
}

박시니어 씨가 두 사람이 좁은 복도에서 만난 상황을 그렸습니다. "두 사람이 동시에 문을 통과하려고 해요.

어떻게 하면 충돌 없이 지나갈 수 있을까요?" Peterson 알고리즘은 두 가지 도구를 사용합니다. **깃발(flag)**과 **턴(turn)**입니다.

깃발은 "나 지나가고 싶어요"라는 의사 표시입니다. 각 프로세스가 하나씩 가지고 있습니다.

깃발을 들면 임계 영역에 진입하고 싶다는 뜻입니다. 턴은 "당신 먼저 가세요"라는 양보의 표시입니다.

둘 다 지나가고 싶을 때 누가 먼저 갈지 결정합니다. 코드를 단계별로 살펴보겠습니다.

첫 번째 단계에서 자신의 깃발을 듭니다. "나 들어가고 싶어요." 두 번째 단계에서 턴을 상대방에게 넘깁니다.

"근데 당신 먼저 가세요." 세 번째 단계에서 대기 조건을 확인합니다. 상대방도 깃발을 들었고, 내가 양보한 상태라면 기다립니다.

임계 영역을 사용한 후 네 번째 단계에서 깃발을 내립니다. 이 알고리즘이 세 가지 조건을 어떻게 만족하는지 살펴보겠습니다.

상호 배제: 두 프로세스가 동시에 임계 영역에 있을 수 없습니다. 둘 다 깃발을 들었을 때, turn 값은 하나입니다.

한 쪽은 반드시 while 루프에서 대기합니다. 진행: 상대방이 관심이 없으면(깃발을 내렸으면) 즉시 진입합니다.

while 조건의 flag[other]가 false이기 때문입니다. 한정 대기: 한 번 양보하면 상대방이 먼저 들어갑니다.

상대방이 나오면 turn이 바뀝니다. 따라서 무한히 기다리는 일이 없습니다.

Peterson 알고리즘은 소프트웨어만으로 동기화를 구현했다는 점에서 의미가 있습니다. 특별한 하드웨어 지원 없이도 올바른 동기화가 가능하다는 것을 증명했습니다.

하지만 현대 시스템에서는 잘 사용하지 않습니다. 현대 CPU는 명령어 순서를 바꾸는 **재정렬(Reordering)**을 수행합니다.

Peterson 알고리즘은 코드 순서에 의존하기 때문에 재정렬이 발생하면 올바르게 동작하지 않습니다. 또한 두 프로세스만 지원한다는 한계도 있습니다.

그래서 실무에서는 하드웨어가 지원하는 원자적 명령어(Compare-And-Swap 등)를 기반으로 한 동기화 도구를 사용합니다. 하지만 Peterson 알고리즘의 아이디어, 의사 표시와 양보의 조합은 여전히 동기화 이론의 기초가 됩니다.

김개발 씨가 감탄했습니다. "깃발과 턴, 정말 우아한 해결책이네요." 박시니어 씨가 마무리했습니다.

"동기화의 기본을 이해하면 어떤 동기화 도구를 만나도 원리를 파악할 수 있어요. 오늘 배운 내용을 잘 기억해 두세요."

실전 팁

💡 - Peterson 알고리즘은 면접에서 자주 나오는 주제입니다. 원리를 정확히 이해하세요.

  • 실무에서는 언어가 제공하는 동기화 도구를 사용하되, 내부 원리를 알아두면 디버깅에 도움이 됩니다.

이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!

#OS#ProcessSync#RaceCondition#CriticalSection#MutualExclusion#Operating System

댓글 (0)

댓글을 작성하려면 로그인이 필요합니다.