컴퓨터를 사용하면 여러 프로세스와 스레드들이 바쁘게 동작한다.
그 과정에서 프로세스 간 메시지를 전송하거나, 공유메모리를 통해 공유된 자원에 여러 개의 프로세스가 동시에 접근할 때, 임계구역(critical Section)
문제가 발생할 수 있다.
임계구역(critical section)
은 동시에 접근하면 안되는 공유 자원에 접근하는 코드블럭을 의미한다.
이를 해결하기 위해 데이터에 한 번에 하나의 프로세스 혹은 스레드만 접근할 수 있도록 제한을 두는 동기화 방식을 취해야 한다.
이 동기화 방식에 대표적으로 뮤텍스(Mutex)
와 세마포어(Semaphore)
가 있다.
공유 자원의 데이터 혹은 임계구역(critical section)에 하나의 프로세스나 스레드만 접근하도록 막아준다.
즉, 여러 프로세스나 스레드들이 서로 겹치지 않고 단독으로 실행하도록 상호배제를 보장한다.
- 핵심은 key(어떤 객체)를 기반으로 한 상호배제 방식이다.
- 공유 자원이나 임계 구역(critical section)에 접근하려면 key를 가진 프로세스나 스레드만 가능하다.
- 공유 자원의 접근을 관리하기 위해 동기화 or
락(Lock)
을 사용한다.
락(Lock)
은 자원에 대한 접근에 제한을 강제하기 위한 동기화 매커니즘이다. 임계 구역에 접근할 때 스레드나 프로세스는 락을 획득(취득 불가 상태로 전환)해야하고, 해당 프로세스나 스레드는 임계구역을 벗어날 때 락을 반환(취득 가능 상태로 전환) 한다.
대표적인 예시가 화장실이 하나 밖에 없는 식당이다.
화장실에 가려면 키를 가져가야 하고, 만약 다른사람이 화장실을 이용하려면 key가 있을때까지 기다려야 한다.
이 상황에서 사람이 프로세스나 스레드이고, 화장실이 공유자원, 화장실 키가 객체에 해당한다.
뮤텍스를 구현한 알고리즘으로는 아래와 같은 것들이 존재한다.
(뮤텍스의 프로세스 진입, 할당, 종료 등에 관한 구현)
- 데커(Dekker) 알고리즘
- 피터슨 알고리즘
- 제과점 알고리즘
공유 자원의 데이터 혹은 임계구역(critical section)에 설정한 수 만큼의 프로세스나 스레드만 접근하도록 막아준다.
동시에 접근할 수 있는 프로세스나 스레드의 수를 세마포어 변수를 통해 관리하며 상호배제를 보장한다.
- 동시 접근이 가능한 프로세스와 스레드의 수를 나타내는 세마포어 변수 값이 존재
- 접근하는 프로세스나 스레드들이 변수의 값을 변경
- 변수 값을 통해 현재 접근이 가능한지 아닌지를 판단
- 만약 사용할 수 없는 상황이라면 일정시간 대기한다.
세마포어도 화장실 식당을 예로 들수있다.
이번에는 화장실이 한 개가 아니라 3개이고, 현재 이용가능한 화장실 수를 표시하는 전광판이 있다고 한다.
만약 한명이 이용하면 전광판 수는 2가 되고 또 한명이 들어가면 수는 1이 된다.
사용을 끝내고 한명이 나오면 수는 다시 2가된다.
이 상황에서 전광판의 수가 세마포어 변수 값이자, 이용할 수 있는 프로세스나 스레드의 수이다.
얼핏보면 비슷해 보이는 두 방식이지만, 가장 큰 차이점은 동기화 대상의 수이다.
- 뮤텍스는 동기화 대상이 1개, 세마포어는 동기화 대상이 1개 이상
- 뮤텍스는 자원의 소유가 가능하지만 세마포어는 불가능
- 뮤텍스는 상태가 0, 1뿐이므로 락을 가질 수 있고 소유하고 있는 스레드만이 뮤텍스를 해제할 수 있다.
- 데이터 무결성을 보장할 수 없다.
- 모든 데드락*을 해결할 수 없다
* 데드락(Dead Lock, 교착 상태) 은 OS 혹은 소프트웨어의 잘못된 자원 관리로 인하여 둘 이상의 프로세스가 서로가 점유한 자원을 기다리는 현상을 말한다.