소프트웨어를 개발하다 보면, 공유되어야 할 자원이 존재할 수 있습니다.

공유자원은 서로 다른 두 태스크가 각자 처리를 마친 후, 결과가 하나로 취합되어야 하는 경우에 필요합니다.

하나로 취합하는 경우, 상호 배제 개념이 중요합니다.


싱글 테스크 와 멀티 테스크

싱글 태스크(싱글 프로세스 + 싱글 스레드) 프로그램이면 문제가 되질 않습니다. 두 태스크는 순차적으로 처리되므로, 공유자원의 동시성 문제가 존재하지 않기 때문입니다.

반면에 멀티 태스크(멀티 프로세스 또는 멀티 스레드) 프로그램이면 문제가 발생할 수 있습니다. 두 태스크가 동시적으로 처리되면서 공유자원이 예기치 못한 결과로 취합될 수 있기 때문입니다.

다음은 은행 입-출금 기능이 싱글 태스크, 멀티 태스크로 구현된 예시입니다.

싱글 테스크

보유 금액: 50,000 (공유 자원)

입금 태스크

  • 현재 보유된 금액을 조회. (50,000)
  • 입금할 금액을 확인 (10,000)
  • 입금 처리. (50,000 + 10,000)

출금 태스크

  • 현재 보유된 금액을 조회. (60,000)
  • 출금할 금액을 확인 (20,000)
  • 출금 처리. (60,000 - 20,000)

최종 보유금액은 40,000(40,000) 이 됩니다.

멀티 테스크

보유 금액: 50,000 (공유 자원)

입금 테스크

  • 현재 보유된 금액을 조회 (50,000)

  • 입금할 금액을 확인 (10,000)

  • 입금 처리. (50,000 + 10,000)

최종 보유금액은 60,000(40,000) 이 됩니다.

출금 테스크

  • 현재 보유된 금액을 조회 (50,000)

  • 출금할 금액을 확인 (20,000)
  • 출금 처리. (50,000 - 20,000)

임계영역

위 예시에서 살펴봤다시피,

멀티 태스크 프로그램을 개발하면, 공유자원을 사용하는 부분을 순차적으로 처리하도록 보장해야 합니다. 이때, 순차적으로 처리해야 하는 부분을 임계영역 이라 일컫습니다.

임계영역 이 순차적으로 처리될 수 있게 하는 방법은 크게 2가지가 있습니다.

  • 뮤텍스(Mutex)
  • 세마포어(Semaphore)


뮤텍스

자원의 선점을 통해, 순차 처리를 수행하는 방법입니다.

이때, 선점될 자원은 하나의 객체로 처리 되며 이를 Lock 또는 Key 라고 부릅니다.

하나의 태스크가 임계 영역을 진입할 때, Lock을 획득하고 진입 하는 방식입니다. 이렇게 되면 다른 태스크들은 Lock을 획득 할 수 있을때 까지 줄지어서 기다리게 됩니다.

Lock을 획득한 태스크가 임계 영역을 처리하고 나면 Lock을 반납하게 됩니다. 그 후, 대기하던 태스크들 중 하나가 Lock을 획득하여 임계 영역을 수행하게 됩니다.

뮤텍스는 단일 공유 자원 처리에 적합

만약 각 태스크가 공유 자원이 2개 이상 필요한 경우는 어떨까요?

각 자원에 대한 Lock 을 생성하고 태스크에 두개의 Lock 에 대한 처리가 필요하게 됩니다.

이는 공유 자원 추가로 인해 변경 사항이 모든 테스크에 반영되어야 하므로, 유지보수를 어렵게 만드는 요인이 됩니다.

또한 공유 자원 개수가 많아 지면 분기 처리도 복잡하고 어려워 지는 문제도 발생합니다.


세마포어

뮤텍스의 다중 공유 자원 처리에 대한 단점을 보완한 방법입니다.

세마포어는 하나의 자원에 대한 락킹 개념보다 조금더 나아가, 자원 사용 카운팅 기법으로 순차 처리를 보장하는 방법입니다.

테스크가 임계 영역을 진입할 때, 진입 가능한 숫자를 참고합니다.

자원 사용 카운팅이 0보다 크다면, 테스크가 임계 영역을 집입하고 자원 사용 카운팅을 하나 감소시킵니다.

만약, 자원 사용 카운팅이 0이라면 테스크는 추가 카운팅이 생길 때 까지 대기하게 됩니다.


데드락

앞서 살펴본 2가지 방법은 널리 사용되고 있는 기본적인 개념입니다.

하지만, 공유 자원을 2개 이상 사용하는 임계 영역을 처리하는 경우 교착 상태가 발생할 수 있습니다.

공유 자원 A, B 가 있다고 가정할 때, 다음의 뮤텍스 방법은 교착 상태 즉, 데드락이 발생할 수 있습니다.

TASK-1

  • Locking(A)
  • Locking(B)

TASK-2

  • Locking(B)
  • Locking(A)

위 예시는 TASK-1공유 자원 B의 락이 해제 되길 기다리고 있으며, 반대로 TASK-2공유 자원A가 해제 되길 기다리고 있습니다. 이는 결국 무한정 대기하게 되는 데드락이 발생하게 됩니다.

세마포어 기법도 마찬가지로 적용됩니다.

데드락 해결 방법

해결 방법은 여러 가지가 존재하며, 상황에 맞게 처리하는것이 중요합니다.

  • 타임아웃 설정

    자원의 대기 타임아웃을 설정하여 교착 상태에 빠진 테스크중 하나를 타임아웃으로 포기하게 하는 방법 입니다.

  • 진입 순서 일치

    공유자원의 임계영역 진입 처리 순서를 동일하게 하여 자원 요청 방향이 원형을 이루지 않도록 처리하는 방법입니다.


정리

  • 뮤텍스는 하나의 락 객체를 통해 임계 영역이 하나의 태스크만 처리할 수 있도록 고안된 방법입니다.
  • 세마포어는 공유자원 접근 가능 카운트를 정의해, 정의한 수 만큼 태스크가 처리할 수 있도록 고안된 방법입니다.
  • 공유 자원을 2개 이상 사용하는 임계영역은 데드락이 발생 할 수 있으므로, 유념해야 합니다.
  • 세마포어의 카운팅을 1로 하면 뮤텍스와 같은 효과를 누릴 수 있습니다.

'운영체제' 카테고리의 다른 글

[운영체제] 스레드  (0) 2021.07.22
[운영체제] 프로세스  (0) 2021.07.21

포스팅이 도움 되셨다면, 커피 한잔 후원해주세요!
더 좋은 포스팅 작성에 큰 힘이 됩니다.

Buy me a coffeeBuy me a coffee

+ Recent posts