교착 상태 예방

이찬영·2021년 8월 26일
0

OS

목록 보기
19/35

교착 상태 예방

교착 상태가 발생하지 않도록 최소한 하나가 성립하지 않도록 보장한다. 이러한 기법을 예방이라고 한다. 문제점으로는 장치의 이용률이 낮아지고 시스템 총 처리율이 감소한다는것이다.

상호 배제

상호 배제를 하지 않음으로써 교착상태를 예방한다. 가장 좋은 예는 읽기-전용 파일이 공유 가능한 자원의 좋은 예이다. 여러 스레드가 읽기 전용의 파일을 열면, 그 파일에는 동시 접근을 허용한다. 다른 프로세스는 공유 가능한 자원을 위해 기다릴 필요가 없다. 하지만 이 방법으로는 근본적으로 해결할 수 없는데 이는 모든 자원이 공유 가능한 자원이 아니기 때문이다. 예를들어 mutex 락은 동시에 여러 스레드가 공유할 수 없다.

점유 대기

시스템에서 점유 대기 조건이 발생하지 않도록 하기 위해선 스레드가 자원을 요청할 때 다른 자원을 보유하지 않도록 해야한다.

  1. 스레드가 실행하기 전에 모든 자원을 요청하고 할당해야한다.
    자원 요청이 동적으로 이루어지는 시스템에서는 실용적이지 않다.
  2. 스레드가 자원을 가지고 있지 않을때만 자원 요청을 할 수 있다.
    추가 자원 요청시 가지고 있는 자원을 모두 반납하고 다시 요청하여야 한다.

위 두 방법의 해결도 문제를 가지고 있다. 첫째는 자원이 할당 되었지만 장기간 사용하지 않아 자원 이용률이 낮아지게 된다. 둘째는 기아가 발생할 수 있다. 인기 있는 여러 개의 자원이 필요한 스레드는 필요한 자원 중 적어도 하나는 항상 다른 스레드에 할당되므로 무한정 대기해야 할 수 있다.

비선점

우리는 비선점이 성립되지 않기 위해 자원을 선점 가능하도록 할 수 있다.

  1. 만약 어떤 자원을 점유하는 스레드가 즉시 할당할 수 없는 자원을 요청하면, 현재 내 스레드가 점유한 모든 자원이 선점 가능해진다. 다시 말해 내가 가진 자원들이 묵시적으로 방출 된다.
  2. 방출된 자원들은 해당 자원을 기다리는 스레드의 자원 리스트에 추가 된다.
  3. 이후 스레드는 자신이 요청하고 있는 새로운 자원과 이미 점유(방출된 자원)했던 모든 자원들을 다시 획득할 수 있을때 다시 시작 된다.

아래는 다른 방법을 설명하겠다.

  1. 한 스레드가 자원들을 요청하면 우리는 사용가능한 자원들인지 검사한다.
  2. 만약 사용가능하다면 이들을 할당한다.
  3. 반대의 경우라면, 그 자원들이 추가의 자원을 위해 대기하고 있는 다른 스레드에 할당되어 있는지를 검사한다.
  4. 대기중인 다른 스레드에서 그 자원들이 있다면 그 자원을 선점하여 내 스레드가 점유하게 된다.
  5. 대기중인 다른 스레드에도 해당 자원이 없다면 사용중인 자원이 방출될때 까지 대기하여야한다.
    (스레드가 대기하는 동안, 스레드의 자원들 중 일부는 다른 스레드가 이들을 요청하는 경우에만 선점될 수 있으며, 스레드가 요청중인 새로운 자원을 할당받고 또한 대기 중에 선점되었던 모든 자원을 회복할 때에만 다시 시작 가능하다.)

일반적으로 해당 방법은 mutex락과 세마포같은 자원에는 적용될 수 없다. CPU레지스터나 데이터베이스 트랜잭션처럼 그 상태가 쉽게 저장되고 후에 복원될 수 있는 자원에 종종 적용된다.

순환 대기

위에 설명한 3가지 방법은 대부분 실용적이지 않은 방법이다. 순환대기 조건을 무효화 하면서 실용적인 해결책을 제공할 수 있다.
첫번째 방법으로는 모든 자원 유형에 전체적인 순서를 부여하여, 각 프로세스가 열거된 순서대로 오름차순으로 자원을 요청하도록 요구하는 것이다.

// 내용 추가

하지만 순서나 계층 구조를 정하는것 그 자체만으로는 교착상태를 예방할 수 없다. 예를 들어 송금 기능을 하는 함수가 있다고 가정하자.

void transaction(Account from, Account to, double amount){
	mutex lock1, lock2;
	lock1 = get_lock(from);
	lock2 = get_lock(to);
    
	acquire(lock1);
		acquire(lock2);
        
			withdraw(from, amount);
			deposit(to, amount);
        
		release(lock2);
	release(lock1);
}

만약 transaction(checking_account, savings_account, 25.0)transaction(savings_account, checking_account, 25.0)이 동시에 호출된다면 교착 상태를 유발할 수 있다.

0개의 댓글