레이스 컨디션 동기화

2025. 6. 5. 19:11·Deep Dives/CS Fundamentals
목차
  1. 레이스 컨디션의 원인
  2. 레이스 컨디션의 문제점
  3. 레이스 컨디션 방지 방법
  4. 데드락
  5. 데드락의 발생 조건
  6. 데드락 예시
  7. 데드락 해결 방법
  8. 데드락 방지를 위한 예시
  9. 1) 자원 요청 순서 제어
  10. 2) 선점 가능 자원 관리

레이스 컨디션은 컴퓨터 프로그램의 병렬 처리나 멀티스레딩 환경에서 발생할 수 있는 문제 중 하나로,

여러 스레드가 동시에 공유 자원에 접근하고 수정할 때 의도치 않은 결과가 나오는 상황입니다.

이 문제는 주로 스레드 간의 실행 순서가 예측 불가능할 때 발생하며, 결과적으로 프로그램이 비정상적으로 동작하거나 버그가 생기게 됩니다.

레이스 컨디션의 원인

레이스 컨디션은 공유 자원에 대해 동기화되지 않은 접근이 있을 때 발생합니다.

예를 들어, 두 스레드가 동시에 동일한 변수를 읽고, 각각 값을 변경한 뒤 저장하는 과정을 동시에 수행하게 된다면, 그 결과는 의도했던 것과 다를 수 있습니다.

balance라는 변수가 있고, 이 변수에 두 스레드가 동시에 접근하여 값을 업데이트하려고 할 때, 스레드 A와 스레드 B가 다음과 같은 순서로 작업을 수행한다고 가정해 보겠습니다.

  1. 스레드 A가 balance 값을 읽습니다. (예: balance = 100)
  2. 스레드 B도 동시에 balance 값을 읽습니다. (여전히 balance = 100)
  3. 스레드 A는 balance 값을 50 증가시키고, 값을 저장하려 합니다. (balance = 150)
  4. 스레드 B는 balance 값을 30 증가시키고, 값을 저장하려 합니다. (balance = 130)

위와 같은 상황에서는 결국 balance 값이 130으로 저장됩니다.

그러나 스레드 A가 먼저 수행될 것이라고 예상했던 경우에는 balance 값이 150이어야 할 것으로 기대했겠죠.

이런 실행 순서에 따른 결과값의 차이가 바로 레이스 컨디션이 발생한 상황입니다.

let balance = 100;

async function deposit(amount) {
  const newBalance = balance + amount;
  await new Promise(resolve => setTimeout(resolve, 100)); 
  balance = newBalance;
}

async function withdraw(amount) {
  const newBalance = balance - amount;
  await new Promise(resolve => setTimeout(resolve, 100)); 
  balance = newBalance;
}

deposit(50);
withdraw(30);

console.log(balance); 

위 코드에서는 balance 값을 업데이트하는 deposit과 withdraw 함수가 동시에 호출되면서 서로의 작업이 덮어씌워질 수 있습니다.

이를 해결하기 위해 여러 동기화 기법을 사용하여 안전하게 제어할 수 있습니다.

레이스 컨디션의 문제점

레이스 컨디션은 여러 가지 문제를 일으킬 수 있습니다. 대표적인 문제는 다음과 같습니다.

  • 예측 불가능한 동작: 레이스 컨디션이 발생한 코드의 결과는 실행할 때마다 다를 수 있습니다. 이는 예측하기 어렵고, 디버깅하기도 매우 힘듭니다.
  • 데이터 손상: 여러 스레드가 동시에 데이터를 수정할 때 일부 스레드의 작업 결과가 유실되거나 손상될 수 있습니다.
  • 프로그램의 비정상 종료: 예기치 못한 상태에서 발생한 오류로 인해 프로그램이 비정상적으로 종료될 수 있습니다.

레이스 컨디션 방지 방법

레이스 컨디션을 방지하기 위해서는 동기화(Synchronization) 기법을 사용하여 여러 스레드가 동시에 공유 자원에 접근하지 못하도록 해야 합니다. 대표적인 동기화 기법은 다음과 같습니다.

  1. 뮤텍스(Mutex): 뮤텍스는 Mutual Exclusion(상호 배제)의 약자로, 하나의 스레드가 자원을 사용하고 있을 때 다른 스레드가 접근하지 못하도록 막는 역할을 합니다.
    class Mutex {
      constructor() {
        this.locked = false;
      }
    
      async lock() {
        while (this.locked) {
          await new Promise(resolve => setTimeout(resolve, 10)); // 잠긴 상태 대기
        }
        this.locked = true;
      }
    
      unlock() {
        this.locked = false;
      }
    }
    
    const mutex = new Mutex();
    
    async function safeDeposit(amount) {
      await mutex.lock();
      const newBalance = balance + amount;
      await new Promise(resolve => setTimeout(resolve, 100)); // 비동기 지연
      balance = newBalance;
      mutex.unlock();
    }
    
    async function safeWithdraw(amount) {
      await mutex.lock();
      const newBalance = balance - amount;
      await new Promise(resolve => setTimeout(resolve, 100)); // 비동기 지연
      balance = newBalance;
      mutex.unlock();
    }
    
    safeDeposit(50);
    safeWithdraw(30);
    
  2. 뮤텍스를 사용하면 한 번에 하나의 스레드만 자원에 접근할 수 있도록 보장합니다.
  3. 세마포어(Semaphore): 세마포어는 자원에 접근할 수 있는 스레드의 수를 제한하는 기법입니다. 예를 들어, 자원에 동시에 최대 3개의 스레드만 접근할 수 있도록 제한할 수 있습니다.
  4. class Semaphore { constructor(max) { this.max = max; this.count = 0; this.queue = []; } async acquire() { if (this.count < this.max) { this.count++; } else { await new Promise(resolve => this.queue.push(resolve)); } } release() { this.count--; if (this.queue.length > 0) { const next = this.queue.shift(); next(); this.count++; } } } const semaphore = new Semaphore(2); async function accessResource(id) { await semaphore.acquire(); console.log(`Resource accessed by ${id}`); await new Promise(resolve => setTimeout(resolve, 100)); console.log(`Resource released by ${id}`); semaphore.release(); } accessResource(1); accessResource(2); accessResource(3);
  5. 락(Lock): 락을 사용하면 특정 코드 블록에 대해 스레드가 순차적으로 접근하도록 제한할 수 있습니다.
    class Lock {
      constructor() {
        this.promise = Promise.resolve();
      }
    
      async acquire() {
        let release;
        const lock = new Promise(resolve => (release = resolve));
        const previous = this.promise;
        this.promise = lock;
        await previous;
        return release;
      }
    }
    
    const lock = new Lock();
    
    async function lockedAccess(id) {
      const release = await lock.acquire();
      console.log(`Locked access by ${id}`);
      await new Promise(resolve => setTimeout(resolve, 100)); 
      console.log(`Released access by ${id}`);
      release();
    }
    
    lockedAccess(1);
    lockedAccess(2); 
    
  6. 락이 걸려 있는 코드 블록은 하나의 스레드가 사용 중일 때 다른 스레드가 접근할 수 없게 되어, 공유 자원의 접근을 안전하게 제어할 수 있습니다.
  7. 모니터(Monitor): 모니터는 락과 조건 변수를 결합한 구조입니다. 락을 사용하여 자원에 대한 접근을 제어하고, 조건 변수를 통해 스레드가 특정 조건을 만족할 때까지 대기하도록 할 수 있습니다. 이를 통해 더욱 세밀한 동기화가 가능합니다.
  8. class Monitor { constructor() { this.queue = []; this.available = true; } async enter() { if (this.available) { this.available = false; return; } await new Promise(resolve => this.queue.push(resolve)); } exit() { this.available = true; if (this.queue.length > 0) { const next = this.queue.shift(); next(); this.available = false; } } } const monitor = new Monitor(); async function monitoredAccess(id) { await monitor.enter(); console.log(`Entered monitor by ${id}`); await new Promise(resolve => setTimeout(resolve, 100)); console.log(`Exited monitor by ${id}`); monitor.exit(); } monitoredAccess(1); monitoredAccess(2);

뮤텍스와 락은 모두 자원에 대한 접근을 제어하는 동기화 기법이지만, 사용 목적과 개념적으로 약간의 차이가 있습니다.

두 개념이 매우 비슷하게 느껴질 수 있으므로, 각각의 역할과 차이점을 조금 더 깊이 설명하겠습니다.

1. 뮤텍스(Mutex: Mutual Exclusion)

자원에 한 번에 하나의 스레드만 접근할 수 있도록 보장합니다. 뮤텍스는 자원에 대한 소유권을 부여하여 자원을 사용하는 스레드가 끝날 때까지 다른 스레드가 접근하지 못하게 합니다.

  • 상태: 뮤텍스는 잠금(Lock)과 해제(Unlock) 두 가지 상태만 있습니다.
  • 소유권: 뮤텍스는 소유권 개념이 있어서, 한 스레드가 뮤텍스를 획득하면 그 스레드만이 해당 자원에 접근할 수 있습니다. 작업이 끝나면 스레드는 뮤텍스를 해제하고 다른 스레드가 자원에 접근할 수 있습니다.
  • 목적: 하나의 스레드만 자원에 접근하게 하기 위해 사용됩니다.

2. 락(Lock)

락은 더 넓은 개념으로, 뮤텍스를 포함하여 자원에 대한 접근을 제어하는 다양한 방식의 동기화 메커니즘을 의미합니다. 뮤텍스도 락의 일종이지만, 락은 다음과 같은 특징들이 있어 조금 더 유연합니다.

  • 다양한 상태: 락은 뮤텍스와 달리 읽기 잠금(Read Lock), 쓰기 잠금(Write Lock) 등 다양한 형태의 잠금을 지원할 수 있습니다.
  • 예를 들어, 여러 스레드가 동시에 자원을 읽는 것은 가능하지만, 쓰기 작업이 필요할 때는 한 번에 하나의 스레드만 접근하도록 할 수 있습니다.
  • 소유권의 유연성: 락은 뮤텍스보다 소유권 관리에 있어 덜 엄격할 수 있습니다. 뮤텍스가 소유권을 강하게 요구하는 반면, 락은 다양한 방식으로 공유 자원에 접근을 제어할 수 있습니다.
  • 목적: 자원의 접근을 좀 더 유연하게 관리하려는 경우에 사용됩니다. 여러 스레드가 동시에 자원에 접근하는 것을 허용하면서도 데이터의 무결성을 지킬 수 있습니다.

아래는 읽기-쓰기 락을 구현한 예제입니다. 여러 스레드가 동시에 읽기 작업은 수행할 수 있지만, 쓰기 작업은 단일 스레드만 수행할 수 있도록 합니다.

class ReadWriteLock {
  constructor() {
    this.readers = 0;
    this.writing = false;
  }

  async readLock() {
    while (this.writing) {
      await new Promise(resolve => setTimeout(resolve, 10)); 
    }
    this.readers++;
  }

  readUnlock() {
    this.readers--;
  }

  async writeLock() {
    while (this.writing || this.readers > 0) {
      await new Promise(resolve => setTimeout(resolve, 10)); 
    }
    this.writing = true;
  }

  writeUnlock() {
    this.writing = false;
  }
}

위 ReadWriteLock 클래스에서 readLock()을 통해 여러 스레드가 동시에 읽기 작업을 할 수 있지만,

writeLock()은 읽기 중이거나 쓰기 중이면 대기 상태에 들어가게 됩니다. 이로써 읽기-쓰기 락을 구현하여 자원 접근의 유연성을 높였습니다.

데드락

데드락(Deadlock)은 여러 프로세스나 스레드가 서로 자원을 기다리며 무한히 대기하는 상태에 빠지는 문제입니다.

이 상태가 발생하면 시스템이 아무 일도 수행하지 못하게 되므로 매우 치명적입니다.

데드락은 주로 병렬 처리 환경에서 발생하며, 특히 여러 자원을 동시에 필요로 하는 상황에서 자주 발생합니다.

데드락의 발생 조건

데드락이 발생하기 위해서는 네 가지 조건이 동시에 만족되어야 합니다. 이를 데드락의 4가지 필요 조건이라고 부릅니다.

  • 상호 배제(Mutual Exclusion): 자원은 동시에 하나의 프로세스만 사용할 수 있습니다. 즉, 한 번에 하나의 프로세스만 자원을 사용할 수 있도록 접근이 제한됩니다.
  • 점유 대기(Hold and Wait): 어떤 프로세스가 이미 자원을 점유한 상태에서, 추가로 다른 자원을 기다리며 대기합니다.
  • 비선점(No Preemption): 한 프로세스가 점유한 자원을 다른 프로세스가 강제로 빼앗을 수 없습니다. 자원을 점유한 프로세스가 스스로 자원을 해제할 때까지 기다려야 합니다.
  • 환형 대기(Circular Wait): 프로세스 간의 자원 요청이 순환 형태로 얽혀 있는 상태입니다.
  • 예를 들어, 프로세스 A는 프로세스 B가 점유한 자원을 기다리고, 프로세스 B는 프로세스 C의 자원을 기다리며, 마지막으로 프로세스 C는 프로세스 A의 자원을 기다립니다.

데드락 예시

데드락의 발생을 간단한 코드로 예를 들어 보겠습니다. 두 개의 뮤텍스 A와 B를 사용하여 데드락을 설명해 보겠습니다.

const mutexA = new Mutex();
const mutexB = new Mutex();

async function process1() {
  await mutexA.lock();
  console.log("Process 1 locked mutexA");

  await new Promise(resolve => setTimeout(resolve, 100)); 

  await mutexB.lock();
  console.log("Process 1 locked mutexB");

  mutexB.unlock();
  mutexA.unlock();
}

async function process2() {
  await mutexB.lock();
  console.log("Process 2 locked mutexB");

  await new Promise(resolve => setTimeout(resolve, 100)); 

  await mutexA.lock();
  console.log("Process 2 locked mutexA");

  mutexA.unlock();
  mutexB.unlock();
}

process1();
process2();

위 예제에서는 process1은 mutexA를 먼저 잠근 후 mutexB를 기다리고, process2는 mutexB를 먼저 잠근 후 mutexA를 기다립니다.

이렇게 두 프로세스가 서로의 자원을 대기하면서 환형 대기가 발생하고, 결국 데드락 상태에 빠지게 됩니다.

데드락 해결 방법

데드락을 해결하기 위한 방법에는 예방, 회피, 탐지 및 복구의 세 가지 접근 방식이 있습니다.

1) 데드락 예방 (Prevention)

데드락 발생 조건 중 하나 이상을 사전에 제거하여 데드락을 예방하는 방법입니다.

  • 상호 배제 제거: 자원을 공유하거나 여러 프로세스가 동시에 사용할 수 있게 하여 상호 배제 조건을 없애는 방법입니다. 그러나 상호 배제는 데이터 무결성을 위해 필수적인 경우가 많아 완전히 제거하기 어렵습니다.
  • 점유 대기 제거: 자원을 점유하고 있는 상태에서 다른 자원을 대기하지 않도록 하는 방법입니다. 예를 들어, 자원을 요청할 때 한 번에 모든 자원을 한꺼번에 요청하여 점유 대기 상태를 없애는 것입니다.
  • 비선점 제거: 다른 프로세스가 점유하고 있는 자원을 필요로 할 때 해당 자원을 강제로 빼앗도록 하는 방법입니다. 하지만 자원 선점이 가능한 경우는 드물며, 일부 시스템에서는 자원 손실 위험이 있어 비선점을 유지합니다.
  • 환형 대기 제거: 자원을 요청할 때 순서 규칙을 정하여 환형 대기를 방지하는 방법입니다. 예를 들어, 자원들을 순서대로 할당하여 특정 순서에 따라 자원을 요청하도록 하면 환형 대기를 피할 수 있습니다.

2) 데드락 회피 (Avoidance)

데드락이 발생할 수 있는 상황을 미리 예측하고 회피하는 방법입니다. 대표적으로 은행가 알고리즘(Banker's Algorithm)이 있습니다.

은행가 알고리즘은 자원 요청이 들어왔을 때, 자원을 할당한 후에도 시스템이 안전 상태인지 점검합니다. 만약 자원을 할당하면 데드락이 발생할 가능성이 있다면 자원을 할당하지 않고 대기하게 합니다.

3) 데드락 탐지 및 복구 (Detection and Recovery)

데드락을 완전히 방지하기 어려운 경우, 데드락이 발생했는지 탐지하고 이를 해결하는 방법입니다.

  • 데드락 탐지: 그래프를 사용하여 프로세스 간의 자원 요청을 추적하고, 순환 대기 상태가 존재하는지 검사하여 데드락이 발생했는지 확인합니다.
  • 데드락 복구: 데드락이 발생한 경우, 특정 프로세스를 종료하거나 일부 자원을 강제로 해제하여 데드락을 해결합니다.
  • 예를 들어, 데드락 상태에 빠진 프로세스를 강제로 종료하거나, 특정 자원을 빼앗아 해소하는 방법이 있습니다.

데드락 방지를 위한 예시

데드락은 프로세스나 스레드가 서로 자원을 기다리며 무한히 대기하는 상태로, 네 가지 조건이 동시에 만족될 때 발생합니다.

이를 예방하기 위해 자원 요청 순서 제어나 선점 가능 자원 관리 등의 방법을 사용할 수 있습니다.

1) 자원 요청 순서 제어

아래와 같이 자원을 고정된 순서로 요청하여 환형 대기를 방지할 수 있습니다.

async function process1() {
  await mutexA.lock();
  console.log("Process 1 locked mutexA");

  await new Promise(resolve => setTimeout(resolve, 100));

  await mutexB.lock(); 
  console.log("Process 1 locked mutexB");

  mutexB.unlock();
  mutexA.unlock();
}

async function process2() {
  await mutexA.lock(); 
  console.log("Process 2 locked mutexA");

  await new Promise(resolve => setTimeout(resolve, 100));

  await mutexB.lock();
  console.log("Process 2 locked mutexB");

  mutexB.unlock();
  mutexA.unlock();
}

process1();
process2();

위의 예제에서 데드락을 방지하기 위해 자원에 대한 접근 순서를 일관되게 유지하는 방식으로 접근했습니다.

이 방식은 환형 대기(Circular Wait) 조건을 피하는 방법으로, 자원 요청의 순서를 통제하여 서로 교착 상태에 빠지지 않도록 설계한 것입니다.

데드락의 주요 원인 중 하나는 환형 대기 조건입니다. 이는 여러 스레드가 서로 다른 순서로 자원을 요청하면서 자원을 서로 기다리는 순환 대기 상황에 빠지게 되는 것을 의미합니다.

  • Process 1이 mutexA를 잠근 후 mutexB를 요청할 때,
  • 동시에 Process 2가 mutexB를 잠근 후 mutexA를 요청한다면,

서로 자원이 교차로 잠겨 환형 대기 상태가 됩니다. 이 상태에서 서로 필요한 자원을 기다리며 무한 대기에 빠져 데드락이 발생합니다.

이를 방지하기 위해 모든 프로세스가 자원을 동일한 순서로 요청하도록 고정하는 방식을 사용했습니다. 즉, mutexA를 먼저 요청한 후 mutexB를 요청하도록 순서를 고정하면, 다음과 같은 점이 보장됩니다:

  • Process 1과 Process 2가 모두 mutexA를 먼저 요청하므로, mutexA를 획득할 때까지 다른 자원을 기다리는 상황이 발생하지 않습니다.
  • Process 1이 mutexA를 획득한 후 mutexB를 요청하면, Process 2는 mutexA가 해제될 때까지 기다리게 됩니다.
  • 동일한 순서로 요청하므로, Process 1이 mutexA와 mutexB를 모두 해제하기 전까지 Process 2가 두 자원을 동시에 점유하려고 시도하는 상황이 발생하지 않습니다.

이 방식은 구현이 간단하고 효과적이며, 자원의 수가 적을 때 특히 유용합니다. 하지만 다음과 같은 제한 사항도 있습니다.

  • 순서 고정의 한계: 자원의 수가 많아지고, 다양한 프로세스가 복잡한 순서로 자원을 요청해야 할 경우 자원 순서를 일관되게 고정하는 것이 어려울 수 있습니다.
  • 성능 저하 가능성: 모든 프로세스가 고정된 순서로 자원을 기다리기 때문에, 경우에 따라 대기 시간이 길어질 수 있습니다.

2) 선점 가능 자원 관리

선점 가능 자원 관리는 데드락을 방지하기 위해 자원의 소유권을 강제로 회수하여 다른 프로세스가 사용할 수 있도록 하는 방법입니다.

이를 통해 자원을 기다리는 프로세스가 무한히 대기하는 상황을 피하고, 데드락 가능성을 줄일 수 있습니다.

일반적으로 비선점 자원(Non-Preemptive Resource)은 이미 다른 프로세스가 사용 중이면 강제로 빼앗을 수 없는 자원을 뜻합니다.

예를 들어, 파일 쓰기 작업 중이거나 데이터베이스 트랜잭션을 수행 중인 경우, 중간에 자원을 강제로 뺏으면 데이터 무결성에 문제가 생길 수 있으므로 이러한 자원은 비선점 자원입니다.

반면, 선점 가능 자원(Preemptive Resource)은 특정 조건에서 다른 프로세스가 요청할 때 강제로 회수하거나 양도할 수 있는 자원입니다. 예를 들어, 메모리나 CPU 시간 할당이 대표적인 선점 가능 자원입니다.

선점 가능 자원 관리에서 자원이 필요한 프로세스가 자원을 기다리는 상황이 생길 때, 다음과 같은 작업을 수행합니다.

  1. 자원 회수: 현재 자원을 사용 중인 프로세스로부터 자원을 강제로 빼앗아, 필요한 프로세스에 할당합니다.
  2. 작업 재개: 자원이 회수되면, 필요했던 프로세스가 자원을 사용할 수 있게 되어 대기 상태가 해소됩니다.

이 방식을 사용하면, 자원을 가진 프로세스가 일정 시간 이상 자원을 점유하지 못하도록 하여 다른 프로세스도 자원에 접근할 수 있게 합니다.

아래는 자원을 선점 가능한 형태로 관리하는 간단한 JavaScript 예제입니다.

이 코드에서는 PreemptiveResource 클래스를 통해 자원 요청이 있을 때 기존 프로세스를 선점하고 자원을 새로운 프로세스에 할당하는 방식을 보여줍니다.

class PreemptiveResource {
  constructor() {
    this.currentProcess = null;
  }

  request(process) {
    if (this.currentProcess !== null) {
      console.log(`Preempting resource from ${this.currentProcess} to ${process}`);
    } else {
      console.log(`${process} is granted access to the resource`);
    }
    this.currentProcess = process; 
  }

  release() {
    if (this.currentProcess !== null) {
      console.log(`Releasing resource from ${this.currentProcess}`);
      this.currentProcess = null; // 자원 해제
    } else {
      console.log("No process is currently holding the resource");
    }
  }
}

const resource = new PreemptiveResource();

async function process(name, holdTime) {
  console.log(`${name} requests the resource`);
  resource.request(name); 
  

  await new Promise(resolve => setTimeout(resolve, holdTime));
  
  resource.release();
  console.log(`${name} has finished using the resource`);
}

process("Process 1", 2000); 
setTimeout(() => process("Process 2", 1000), 1000); 
setTimeout(() => process("Process 3", 1500), 1500); 

  1. PreemptiveResource 클래스: 이 클래스는 자원을 관리하며, request() 메서드를 통해 자원을 요청하고, release() 메서드를 통해 자원을 해제할 수 있습니다.
    • request(process): 자원을 요청할 때, 현재 자원을 사용 중인 프로세스가 있을 경우 그 프로세스로부터 자원을 선점합니다. 그러면 기존 프로세스는 자원을 잃고, 새로운 프로세스가 자원을 사용하게 됩니다.
    • release(): 현재 자원을 사용 중인 프로세스를 해제합니다.
  2. 프로세스 함수 process: 각 프로세스는 일정 시간 동안 자원을 점유하려고 합니다. 자원을 요청하고, 일정 시간 동안 자원을 점유한 후 자원을 해제합니다.
    • process("Process 1", 2000): Process 1이 2초 동안 자원을 점유하려고 합니다.
    • process("Process 2", 1000): Process 2는 1초 후 자원을 요청합니다. 이때 Process 1이 자원을 점유하고 있다면, Process 2가 자원을 선점하게 됩니다.
    • process("Process 3", 1500): Process 3는 1.5초 후 자원을 요청하며, 상황에 따라 자원을 선점할 수 있습니다.

실행 결과 최초에는 Process 1이 자원을 점유합니다. 1초 후 Process 2가 자원을 요청할 때, Process 1이 점유하고 있던 자원을 선점하고 자원을 사용하게 됩니다.

그 이후에 Process 3가 자원을 요청하여, 자원이 선점 가능한 상태라면 자원을 사용할 수 있게 됩니다.

이렇게 선점 가능 자원 관리를 통해 프로세스가 자원을 점유하고 오랫동안 해제하지 않는 상황에서 데드락이 발생할 가능성을 줄일 수 있습니다.

다만, 특정 프로세스의 작업이 중단되고 자원이 회수될 수 있으므로 데이터의 일관성 문제가 발생할 수 있습니다.

특히 자원 선점 시 프로세스가 다시 자원을 확보할 때까지 상태를 저장하거나 작업을 안전하게 중단할 방법이 필요합니다.

선점 가능 자원 관리 방법은 데드락 방지에 매우 유용하지만, 자원의 회수와 할당이 자원의 일관성에 미치는 영향을 충분히 고려해야 합니다.

이처럼 데드락을 방지하거나 해결하는 방법은 상황에 따라 다르며, 데드락 회피와 탐지, 복구 기법을 적절히 조합하여 시스템의 안정성을 높이는 것이 중요합니다.

'Deep Dives > CS Fundamentals' 카테고리의 다른 글

네트워크 프로토콜: TCP vs UDP (feat 면접 준비)  (0) 2025.06.25
가상 메모리(Virtual Memory)  (1) 2025.06.06
레이스 컨디션 데드락  (3) 2025.06.02
컨텍스트 스위칭  (3) 2025.06.01
프로세스와 스레드  (0) 2025.05.31
  1. 레이스 컨디션의 원인
  2. 레이스 컨디션의 문제점
  3. 레이스 컨디션 방지 방법
  4. 데드락
  5. 데드락의 발생 조건
  6. 데드락 예시
  7. 데드락 해결 방법
  8. 데드락 방지를 위한 예시
  9. 1) 자원 요청 순서 제어
  10. 2) 선점 가능 자원 관리
'Deep Dives/CS Fundamentals' 카테고리의 다른 글
  • 네트워크 프로토콜: TCP vs UDP (feat 면접 준비)
  • 가상 메모리(Virtual Memory)
  • 레이스 컨디션 데드락
  • 컨텍스트 스위칭
Jcob.moon
Jcob.moon
반가워요~ 하루하루 꾸준히 코딩 작성하는 곳입니다 !!
  • Jcob.moon
    Pixelated Thoughts
    Jcob.moon
  • 전체
    오늘
    어제
    • HelloWorld (178)
      • Daily Logs (126)
        • TIL (Today I Learned) (65)
        • Algorithm Practice (55)
        • Dev Book Notes (6)
      • Deep Dives (36)
        • 문제 해결 (Troubleshooting) (3)
        • CS Fundamentals (22)
        • Career Prep (4)
        • Technical Notes (7)
      • Project Log (7)
      • Any (3)
      • Cooperation (5)
        • Github (2)
        • Conventions (1)
        • Git (1)
        • Postman (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 최근 댓글

  • hELLO· Designed By정상우.v4.10.3
Jcob.moon
레이스 컨디션 동기화

개인정보

  • 티스토리 홈
  • 포럼
  • 로그인
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.