다중 프로그래밍 운영체제에서 여러 프로세스가 데이터를 공유하며 수행될 때 각 프로세스에서 공유 데이터에 접근하는 프로그램 코드 부분을 가리키는 말이다.
공유 데이터에 여러 프로세스가 동시에 접근하면 시간적인 차이 등으로 인하여 잘못된 결과를 만들어 낼 수 있기 때문에 한 프로세스가 위험 부분을 수행하고 있을 때, 즉 공유 데이터에 접근하고 있을 때는 다른 프로세스들이 절대 그 데이터에 접근하지 못하도록 해야 한다.
Mutual Exclusion으로 상호배제 기법이다.
mutex는 스레드 간 공유하는 데이터 영역을 보호하기 위해서 사용한다.
데이터 영역의 보호는 임계영역(critical section)을 만들고 임계영역 내에 단 하나의 스레드만이 진입할 수 있도록 하는 방식을 사용한다.
동일한 메모리를 공유하는 스레드 혹은 프로세스끼리 충돌하지 않게 하기 위해 lock 과 unlock 을 사용하여 충돌 없이 각각 실행되게 한다.
lock 은 임계영역에 진입하기 위해, unlock 은 임계영역을 빠져나와 다른 스레드에게 임계영역을 되돌려주기 위해 사용한다.
만약 스레드가 임계영역에 진입하기 위해 lock 을 시도했는데 다른 스레드가 이미 임계영역에 진입해 있다면, 해당 스레드가 unlock 하여 임계영역을 빠져나올 때까지 기다리게 된다.
예를 들면, 뮤텍스는 화장실이 한 칸만 있는 것과 같다. 화장실 키가 없으면 이미 화장실을 사용 중인 것이고, 키가 있다면 비어있는 것이기 때문에 사용할 수 있다.
화장실을 이미 사용하고 있을 때 누군가 화장실에 들어가려고 하면 키가 없어서 들어갈 수 없다.
대기하고 있다가 화장실에서 누군가 나와서 키가 생기면 이제 들어가서 이용할 수 있다.
화장실을 이용하는 사람이 프로세스 혹은 스레드가 되고 화장실은 공유자원, 화장실 키는 공유자원에 접근하기 위한 어떤 객체이다.
Semaphore는 깃발이라는 뜻으로, 옛날 기찻길에서 깃발을 표식으로 사용하여 파란색일 때는 지나가도 되고 빨간색일 때는 멈추게 해서 다른 기차가 지나간 뒤에 지나가게 하는 용도로 사용했었다.
겹치는 기찻길 부분이 두 기차가 공유하는 임계영역(critical section)이 된다.
세마포어는 공유된 데이터의 개수를 의미한다. 그래서 0 또는 1, 2, ... 등등이 될 수 있다.
여기서 공유자원이 한 개일 때는 세마포어의 값이 0 또는 1이 되는데, 이 경우를 이진 세마포어
(binary semaphore) 라고 하며 mutex와 동일하게 볼 수 있다.
(뮤텍스는 절대 세마포어처럼 사용될 수 없다.)
이와 다르게 0과 1이 아닌 다른 값도 가질 수 있는 세마포어를 카운팅 세마포어(counting semaphore) 혹은 범용 세마포어(general semaphore)라고 한다.
세마포어는 운영체제의 자원을 경쟁적으로 사용하는 다중 프로세스에서 행동을 조정하거나 동기화하는 기술이다.
세마포어는 동기화를 위해 semWait
과 semSignal
이라는 연산을 사용해서 세마포어의 값을 감소/증가시킨다.
semWait
연산은 세마포어의 값을 감소시키고, 값이 음수가 되면 semWait
을 호출한 프로세스가 차단된다.
semSiganl
연산은 세마포어의 값을 증가시키고, 값이 0 또는 음수가 되면 semWait
연산에 의해 차단된 프로세스의 차단을 해제한다.
뮤텍스에서처럼 예를 들면, 세마포어는 화장실이 여러 칸 있고 화장실 입구의 전광판에 몇 칸이 비어있는지가 나오는 것이다.
누군가 화장실을 이용하고자 한다면 입구의 전광판을 보고 빈 칸이 몇 개인지 확인하고, 빈 칸이 1칸 이상이라면 전광판의 개수를 하나 줄인 다음에 화장실에 입장한다.
화장실에서 나올 때는 전광판의 숫자에 하나 더한다.
모든 칸에 사람이 들어가 있어서 전광판의 숫자가 0일 때 누군가 화장실을 이용하고자 한다면 빈 칸이 생길 때까지 대기해야 한다.
마찬가지로 화장실을 이용하는 사람이 프로세스 혹은 스레드가 되고 화장실은 공유자원이 된다.
그리고 화장실의 빈 칸의 개수는 현재 공유자원에 접근할 수 있는 프로세스 혹은 스레드의 개수를 나타낸다.
세마포어는 동기화 대상이 하나 이상일 때, 뮤텍스는 동기화 대상이 하나일 때 사용한다.
처음에는 여기서 말하는 동기화 대상이 뭐지?해서 이해가 안 갔는데, hyunlee님의 설명을 듣고 무릎을 탁 쳤다.
과제에서 뮤텍스를 사용하는 기본 파트의 내용은 다음과 같다.
n명의 철학자가 테이블을 둘러싸고 앉아있을 때, 각 철학자 사이에 포크가 존재한다. 그리고 각자 음식을 가지고 있다.(테이블 중앙에 음식이 하나만 존재한다고 봐도 문제 없는 것 같다.)
각 철학자는 포크 두 개를 동시에 사용해야만 음식을 먹을 수 있다.
여기서 포크가 동기화 대상이다.
두 철학자가 하나의 포크를 같이 사용해야 하는데, 내 옆의 철학자가 이미 쓰고 있다면 자신은 그 포크를 사용할 수 없다. 따라서 음식을 먹을 수도 없다.
이렇게 두 스레드가 하나의 포크를 가지고 사용할 수 있는지 없는지를 알아야 하니까 동기화 대상이 하나인 것이다.
하지만 세마포어를 사용하는 보너스 파트의 내용은 좀 다르다.
n명의 철학자가 테이블을 둘러싸고 앉아있을 때, 철학자 사이에 포크가 존재하는 것이 아니라 테이블 중앙에 포크가 쌓여있는 것이다.
각 철학자가 포크 두 개를 동시에 사용하는 것은 동일하다.
여기서도 포크가 동기화 대상인 것은 마찬가지인데, 모든 철학자가 테이블에 포크가 몇 개 남았는지를 공유해야 한다.
이렇게 프로세스 간에 공유하는 포크가 한 개씩이 아니라 여러 개이므로 동기화 대상이 여러 개인 것이다.
뮤텍스는 lock 혹은 unlock 을 사용하여 잠금을 걸은 스레드만이 임계영역을 나갈 때 잠금을 해제할 수 있다. 하지만 세마포어는 시그널 메커니즘으로 잠금을 걸지 않은 스레드도 시그널을 사용해서 잠금을 해제할 수 있다.
어렵다 어려워...
봐도봐도 어렵고 막 머리에 쏙-하고 들어오진 않는 기분이다.
그래도 처음보다는 훨씬 상황이 나아졌다.
처음 과제를 시작할 때는 뭘 공부해야 할지도 모르겠고 뭘 하라는 건지도 모르겠었는데, 이제는 어떤 걸 구현해야 하는지 뭐가 뭔지 알겠다.
😋🥗🍴
참고한 사이트:
개발자를 꿈꾸는 프로그래머 :: Semaphore란? 세마포어와 뮤텍스의 차이는?
뮤텍스(Mutex)와 세마포어(Semaphore)의 차이
[운영체제]세마포어(semaphore) 완전 쉬운 이해! wait(), signal(), 이진, 계수형