공유 자원
시스템 안에서 각 프로세스, 스레드가 함께 접근할 수 있는 모니터, 프린터, 메모리, 파일, 데이터 등의 자원이나 변수를 의미한다.
경쟁 상태
공유 자원을 둘 이상의 프로세스 또는 스레드가 동시에 읽거나 쓰는 상황을 말하며 동시에 접근을 시도할 때의 타이밍이 예상되는 결과 값에 영향을 줄 수 있는 상태를 의미한다.
임계영역
둘 이상의 프로세스 또는 쓰레드가 공유자원에 접근할 때 순서 등의 이유로 결과가 달라지는 코드영역을 말한다.
이 영역은 한 번에 둘 이상의 프로세스나 쓰레드가 들어갈 수 없게 설계된다.
예시
어떠한 json 변수에 a : 1000 이라는 것이 있고, 프로세스 2개에 각각 a -= 1000 이라는 부분이 있다.
우리가 원하는 결과는 a : -1000 일텐데, 동시에 접근해 a : 0이 되어버릴 수 있다. 이러한 상태를 경쟁 상태, 그리고 a : 1000 이 부분이 임계영역이라고 볼 수 있다.
경쟁 상태 관리의 중요성
경쟁 상태를 잘 해결하지 못하면 데이터 정합성, 데이터 무결성을 지킬지 못할 수 있다.
- 데이터 정합성
- 예상되는 데이터의 값과 다른 것을 의미한다.
- 데이터 무결성
- 데이터가 전송, 저장되고 처리되는 모든 과정에서 변경되거나 손상되지 ㅇ낳고 완전성, 정확성, 일관성을 유지함을 보장하는 특성.
- 데이터의 어떤 규칙을 위반하면 안되는 것을 의미한다.
- ex) 은행에서 0원인 상태의 것에서 출금하는 것
경쟁상태의 해결
경쟁 상태를 해결하는 대표적인 방법으로는 뮤텍스, 세마포어, 모니터 3가지가 있다. 이 방법들은 상호배제, 한정대기, 진행의 융통성의 조건을 만족시키며 경쟁상태를 해결한다.
- 상호배제 : 한 프로세스가 임계영역에 들어갔을 때 다른 프로세스는 들어갈 수 없음.
- 한정대기 : 특정 프로세스가 임계영역 진입을 요청한 후 해당 요청이 승인되기 전까지 다른 프로세스가 임계영역에 진입하는 횟수를 제한하는 것을 말한다.
- 특정 프로세스가 영원히 임계영역에 들어가지 못하게 하는 것을 방지한다.
- 임계영역에 들어가는 우선순위가 높은 프로세스들의 입장 횟수를 제한.
- 진행의 융통성 : 어떠한 프로세스도 임계영역을 사용하지 않는다면 임계영역 외부의 어떠한 프로세스도 들어갈 수 있으며 이 때 프로세스끼리 서로 방해하지 않는 것을 의미.
뮤텍스(mutex)
공유자원을 lock()을 통해 잠금설정하고 사용한 후에 unlock()을 통해 잠금해제가 되는 객체 lock을 기반으로 경쟁상태를 해결한다.
잠금이 설정되면 다른 프로세스나 스레드는 잠긴 코드 영역에 접근할 수 없고 해제는 그와 반대가 된다. 한번에 하나의 프로세스만 임계영역에 있을 수 있다.
세마포어(semaphore)
일반화된 뮤텍스를 말한다. 간단한 정수 S와 두 가지 함수 wait() 및 signal()로 공유자원에 대한 접근을 처리한다.
이를 통해 여러 프로세스가 동시에 임계영역에 접근할 수 있다.
- S : 현재 쓸 수 있는 공유자원의 수
- wait() : S를 1씩 감소시킨다.
- 프로세스가 공유자원을 사용시작하는 것.
- S가 음수가되면 공유자원을 쓸 수 없기 때문에 프로레스는 차단되고 대기열에 프로세스를 넣는다.
- signal() : S를 1씩 증가시킨다.
- 프로세스가 공유자원을 사용을 끝마친 상태를 말한다.
- 이 때 만약 S가 0이하라면 signal을 실행할 때 대기열에 있던 프로세스가 동작하게 된다.
세마포어는 바이너리 세마포어와 카운팅 세마포어로 나뉜다.
바이너리 세마포어
S가 0과 1의 두 가지 값만 가질 수 있는 세마포어이다.
구현의 유사성으로 뮤텍스가 바이너리 세마포어라고 볼 수 있다. 하지만 뮤텍스는 잠금을 기반으로 상호배제가 일어나는 것이고, 세마포어는 신호를 기반으로 상호배제가 일어난다는 차이가 있다.
카운팅 세마포어
S가 여러 개의 값을 가질 수 있는 세마포어를 의미한다.
모니터
둘 이상의 프로세스나 쓰레드가 공유 자원에 안전하게 접근할 수 있도록 공유자원을 숨기고 해당 접근에 대해 인터페이스만 제공하는 객체이다.
이를 통해 공유자원에 대한 작업들을 순차적으로 처리한다.
세마포어와의 차이
모니터가 구현이 더 쉬우며 한 번에 하나의 프로세스만 공유 자원에 접근할 수 있기 떄문에 상호배제가 알아서 된다.
세마포어는 한 번에 여러개의 프로세스가 공유자원에 접근할 수 있다. 이 때문에 상호배제를 명시적으로 구현해야 한다. (그래서 구현이 더 어렵다.) 또한 정수변수를 기반으로 구축된다.
교착상태(deadlock)
두 개 이상의 프로세스들이 서로가 가진 자원을 기다리며 중단된 상태를 의미한다.
이 과정에서 서로의 자원을 유지한 채 다른 프로세스의 자원을 얻기를 기다리는 것이다. 그럼 영원히 서로 자원을 얻지 못하는 상태가 된다.
교착 상태의 원인
교착상태가 발생하기 위한 4가지 필요조건은 아래와 같다.
- 상호배제 : 주어진 시간 내에 하나의 프로세스만 자원을 독점할 수 있다.
- 점유대기 : 특정 프로세스가 점유한 자원을 다른 프로세스가 요청하며 대기하는 상태
- 비선점 : 다른 프로세스의 자원을 강제적으로 가져올 수 없다.
- 환형대기 : 프로세스 A는 프로세스 B의 자원을 요구하고, 프로세스 B는 A의 자원을 요구하는 등 서로가 서로의 자원을 요구하는 상황을 말한다.
교착 상태의 해결
- 자원을 할당할 때 애초에 조건이 성립되지 않도록 설계한다.
- 교착 상태 가능성이 없을 때만 자원이 할당되며, 프로세스가 요청할 자원들의 최대치를 통해 자원 할당 가능 여부를 파악하는 은행원 알고리즘을 쓴다.
- 교착 상태가 발생하면 사이클이 있는지 찾아보고 이에 관련된 프로세스를 하나씩 지운다.
- 교착 상태는 매우 드물게 일어나기 때문에 이를 처리하는 비용이 더 커서 교착상태가 발생하면 사용자가 작업을 종료한다. 현대 운영체제는 이 방법을 채택했다. (응답 없음이 발생하는 이유 중 하나)
은행원 알고리즘
교착상태를 회피하는 알고리즘으로 총 자원의 양과 현재 할당된 자원의 양을 기준으로 안정 또는 불안정 상태로 나누고 안정상태로 가도록 자원을 할당하는 알고리즘.
은행원 알고리즘의 단점
프로세스가 시스템에 들어갈 때 필요한 최대 자원 수를 예측해야 하는데 이를 예측하기 쉽지 않고, 해당 알고리즘에 대한 자원소모량이 증가하게 된다.
그리고 프로그램의 수는 고정되어있지 않고 항상 변하기 때문에 쓰기가 어렵다.