티스토리 뷰
Mutex / Semaphore / Monitor / OS /
아래는 여러 글들을 바탕으로 내가 이해한 뮤텍스, 세마포어, 모니터 간의 차이점이다.
공통점은 세가지 모두 운영체제의 동기화 기법이라는 것이다.
우선 뮤텍스, 모니터와 세마포어의 차이는 개념적으로 전자(뮤텍스,모니터)는 상호배제를 함으로써 임계구역에 하나의 스레드만 들어갈 수 있다는 것이고 후자(세마포어)는 하나의 스레드만 들어가게도 할 수 있고 (binary semaphore) 여러개의 스레드가 들어가게 할 수도 있다(counting semaphore).
그럼 뮤텍스와 모니터의 차이는?
가장 큰 차이는 뮤텍스는 다른 프로세스(애플리케이션)간에 동기화할 때 사용할 수 있다는 것이고 모니터는 하나의 프로세스(애플리케이션)내에 다른 스레드 간에 동기화할 때 사용된다는 것이다. 또한, 뮤텍스는 보통 운영체제 커널,프레임워크,라이브러리에 의해서 제공되는 반면에 모니터는 프레임워크나 라이브러리 그 자체에서 제공된다. 따라서 뮤텍스는 무겁고(heavy-weight) 느리며(slower) 모니터는 가볍고(light-weight) 빠르다(faster).
세마포어와 모니터의 차이에 대해 좀 더 자세하게 보면?
앞서 세마포어는 binary semaphore 아니라 counting semaphore를 제공하는 반면 모니터는 개념적으로 이진 세마포어만 가능하다고 했다.
둘은 이 차이점만 있는 것이 아니다.
Java에서는 모니터를 모든 객체에게 기본적으로 제공하고 있는 반면 C에서는 모니터를 사용할 수 없다.
또한, 세마포어는 실제로는 카운터라는 변수값으로 프로그래머가 상호배제나 오더링의 목적으로 사용시 매번 값을 따로 지정해줘야하는 등 조금 번거롭다. 반면,모니터는 이러한 일들이 캡슐화되어있어서(encapsulation) 개발자는 카운터값을 1로 주냐 0으로 주냐 고민할 필요 없이 synchronized, wait(), notify() 등의 키워드를 이용해 좀 더 편하게 동기화할 수 있다.
아래는 참조한 자료들이며 출처를 밝혀두었다.
------
프로그래밍 언어 수준에서 병행성을 제공하는 기법으로, 세마포어와 뮤텍스가 있습니다.
- 동기화 기법이라고 볼 수 있습니다.
- 세마포어와 뮤텍스 이외에도 모니터, 이벤트 플래그, 메시지, 스핀락 등이 있지만 나중에 포스팅 할 수 있도록 하겠습니다.
동기화
시스템의 자원은 한정적인데 이 한정적인 자원에 여러 스레드가 동시에 접근해서 사용하려하면 문제가 발생할 수도 있습니다. 이런 문제를 방지하기 위해 스레드들에게 하나의 자원에 대한 처리 권한을 주거나 순서를 조정해주는 기법입니다.
임계구역 (Critical Section)
공유자원에 접근하는 프로세스 내부의 코드 영역으로 어떤 한 프로세스가 이 영역을 수행중일 때 다른 프로세스가 같은 영역을 수행한다면 문제가 발생할 수 있습니다.
상호배제 (Mutual Exclusion)
한 프로세스가 공유 자원을 접근하는 임계영역 코드를 수행하고 있으면 다른 프로세스들은 공유 자원을 접근하는 임계영역 코드를 수행할 수 없다는 조건입니다.
- 임계영역을 보호하기 위한 개념
- 둘 이상의 프로세스가 공유자원에 대해 동시에 읽거나 쓰는 것을 방지하기 위한 기법
- 상호배제 기법에는 뮤텍스, 세마포어, 모니터, 메시지 전달 등의 기법이 있습니다.
세마포어 (Semaphores)
프로세스간의 시그널(신호, Signal)을 주고받기 위해 사용되는 정수 값, 리소스의 상태를 나타내는 카운터로 세마포어는 다음 세가지 원자적인 연산만을 지원합니다.
- initialize, decrement, increment
- initialize : 세마포어 초기화. (음이 아닌 정수값으로 초기화)
- decrement : 프로세스를 블록시킬 수 있습니다.
- increment : 블록되었던 프로세스를 깨울 수 있습니다. 이 세마포어를 카운팅 세마포어 또는 범용 세마포어라고 합니다.
세마포어의 값에 따라 운영체제는 프로세스가 즉시 자원을 사용할 지, 자원이 다른 프로세스에 의해 사용 중인걸 알게 될 경우엔 일정 시간을 기다려야 합니다.
프로세스가 자원을 사용하는 동안에는 세마포어 값을 변경함으로서 다른 프로세스들이 기다리게 해야합니다.
- 프로세스간 메시지를 전송하거나 공유메모리를 통해 특정 데이터를 공유하게 될 경우 공유 자원에 여러 프로세스가 접근하면서 문제가 발생하게 됩니다.
+ 하나의 프로세스만 자원에 접근 가능하도록 설정할 때 세마포어를 사용합니다.
이진 세마포어
- 0 또는 1의 값을 가지는 세마포어
뮤텍스 (Mutex)
MUTual EXclusion으로 상호배제라고도 합니다.
0또는 1의 값을 가지는 이진 세마포어와 유사합니다. Critical Section (임계구역)을 가진 스레드들의 실행 시간을 서로 겹치지 않게 단독으로 실행하게 하는 기술입니다.
- 프로세스들의 공유 리소스에 대한 접근을 조율하기 위해 Locking과 Unlocking을 사용합니다.
- 뮤텍스 객체를 두 스레드가 동시에 사용할 수 없습니다.
세마포어와 뮤텍스의 차이
- 세마포어는 뮤텍스가 될 수 있지만, 뮤텍스는 세마포어가 될 수 없습니다.
- 세마포어는 소유할 수 없으며, 뮤텍스는 소유할 수 있고 소유주가 그에 대한 책임을 집니다.
- 뮤텍스의 경우 뮤텍스를 소유하고있는 스레드가 이 뮤텍스를 해제할 수 있습니다. 하지만, 세마포어는 소유하지 않고 있는 스레드가 세마포어를 해제할 수 있습니다.
- 세마포어는 시스템 범위에 걸쳐있고 파일 시스템 상의 파일 형태로 존재합니다. 하지만, 뮤텍스는 프로세스 범위를 가지고 프로그램이 종료될 때 자동으로 지워집니다.
- 세마포어는 동기화 대상이 여러개 일 때, 뮤텍스는 동기화 대상이 오로지 하나 일 때 사용됩니다.
출처: http://wonjayk.tistory.com/250 [배고파서 까먹고 만든 블로그]
운영체제 시간에 나오는 상호배제와 임계구역;;;; 머리가 아파온다. 하지만 그것보다 도대체 동기화 기법중 세마포어, 뮤텍스, 모니터의 차이점이 멀까? 이게 가장 알기 힘들다.
상호배제(Mutual Exclusion), 임계영역(Critical Section/Region)이란?
Multi Threading/Processing 같은 Conccurrent한 환경에서 공유 자원에 동시에 접근할 경우 다양한 문제점이 발생 할 수 있다. 이런 상황을 예방하기 위해 "야 우리 동시에 접근 안하는게 어때?"라는 약속이 필요한데 이게 바로 상호배제이다. 또 임계영역이란 이런 공유 자원에 접근하는 코드 영역을 의미한다.
Mutual Exclusion을 해결하기 위한 방법들1) Mutex 기법
일종의 Locking 매커니즘이다. lock을 가지고 있을 경우에만 공유 데이터에 접근 가능하다. 일부 음식점들은 공용 화장실 관리 차원에서 화장실을 잠궈두고(Locking) 다닌다. 손님들이 화장실에 가려면 주인에게 열쇠를 받은 후 가야한다. 물론 다음 손님이 화장실에 가려면 앞 손님이 열쇠를 반납해야 갈 수 있다. 이렇게 열쇠가 있는-lock을 가지고 있는 경우-에만 공유자원(화장실)에 접근할 수 있다. 이게 바로 Mutex라고 보면 된다. 유의할 점은 Lock에 대한 소유권이 있다는 점이다. 열쇠를 획득한 사람만 반납할 수 있다.
2) Semaphore 기법
세마포어는 동시에 리소스에 접근할 수 있는 '허용 가능한 Counter의 갯수'를 가지고 있는 Counter로 보면 된다. 예를 들면 107호 병실에 방문객용 의자가 5개 있다고 치자. 간호사는 이 병실에 방문자가 5명만 들어갈 수 있도록 허용하고 나머지 방문객들은 밖에서 대기하도록 한다. Counter 갯수만큼 공유자원(병실)에 접근할 수 있다. 이 세마포어 Counter의 갯수에 따라 1개의 경우 Binary Semaphore, 2개 이상의 경우 Counting Semaphore라고 불린다. Binary Semaphore의 경우 개념적으로 Mutex와 같다고 볼 수 있다.
3) Monitor 기법
Mutex(Lock)와 Condition Variables(Queue라고도 함)을 가지고 있는 Synchronization 메카니즘이다. 예를 들어 자바에서 모든 객체는 Object 클래스를 상속 받는다. 이 Object 클래스에는 wait(), notifyAll(), notify() 메소드를 가지고 있는데 이게 바로 Condition Variables 역할이라고 보면 된다. 고로 모든 자바 객체는 Monitor를 가지고 있다. 자바에서는 Mutual Exclusion 해결을 위한 구현체로 Synchronized 키워드가 있다. 예를 들어 Synchronized가 메소드에 선언되어있고, 쓰레드A가 이미 Lock을 획득해서 Critical Section(메소드)을 수행중이라고 가정하자. 쓰레드B가 동일한 메소드를 수행하기 위해 해당 Object의Lock을 획득해야 할 것이다. 이 Lock이 반환될 때까지 대기를 해야하는데 그 때 사용되는게 바로 Monitor다. 쓰레드A가 Lock을 반환하면 쓰레드B는 기다렸다가 Lock을 획득하게 된다. 그리고 Critical Section인 메소드를 수행할 수 있게 된다. 물론 Synchronized 키워드를 사용했을 때 자동적으로 수행되는 내부 동작이고, 별도로 명시적인 Monitor를 구현할 수도 있다.아무튼 Monitor는 이렇게 Mutex(Lock)과 Condition Variables을 이용해서 Mutual Exclustion을 해결하고 있다. 그 외 Monitor의 다른 정의로는 공유자원에 안전하게 접근하기 위해 Mutual Exclusion가 랩핑된 Thread-Safe한 클래스, 객체, 모듈들을 의미하기도 한다.
솔직히 이해가 안간다??????
그럼 차이점이라도 알고가라~ 제발
뮤텍스와 세마포어의 차이점
뮤텍스는 공유자원을 접근할 수 있는 키가 하나인 세마포어랑 같다. 키가 하냐 쓸수 있냐? 여러개 쓸수 있냐의 차이다.
세마포어와 모니터의 차이
세마포어에 비해서 모니터 쪽이 공유자원에 접근할 수 있는 키의 획득과 해제를 모두 처리해서 간단하다. 세마포어는 직접 키해제와 공유자원 접근 처리를 해주어야한다.
자바는 모니터 방식!!!!
출처 https://m.blog.naver.com/PostView.nhn?blogId=koliaok&logNo=220543246779&proxyReferer=https%3A%2F%2Fwww.google.co.kr%2F
운영체제 13장
- 프로세스 관리(10) : 모니터 -
동기화 문제를 해결하기 위해서 우리는 세마포라는 도구를 사용하였다. 하지만 동기화 문제를 해결하는데 세마포만이 사용되지는 않는다. 사실 세마포의 경우 오래된 동기화 도구라고 할 수 있다. 현재 사용되는 도구 중 하나가 모니터이다. 특히 자바 프로그램에서는 모니터에 대한 활용이 높다. 세마포가 어셈블리 언어에 적합한 도구라면 모니터는 그보다 고수준인 언어의 도구라고 할 수 있다.
공유자원과 공유자원에 대한 접근함수가 존재한다. 이러한 구역을 임계구역이라고 한다. 모니터의 경우 두 개의 queue가 있는데 각각 배타동기와 조건동기의 역할을 한다. 배타동기의 queue는 하나의 쓰레드만 공유자원에 접근할 수 있게 하는 작용을 하는 공간이다. 특정 쓰레드가 공유자원을 사용하는 함수를 사용하고 있으면 다른 쓰레드는 접근을 할 수 없고 대기해야 한다. 조건 동기의 queue는 진입 쓰레드가 블록되면서 새 쓰레드가 진입가능하게 하는 공간이다. 새 쓰레드는 조건동기로 블록된 쓰레드를 깨울 수 있다. 깨워진 쓰레드는 현재 쓰레드가 나가면 재진입할 수 있다.
자바의 모니터를 살펴보면서 모니터의 원리를 더욱 알아보도록 하자.
자바의 모든 객체는 모니터가 될 수 있다. 배타 동기는 synchronized 키워드를 사용해서 지정할 수 있고 조건 동기는 wait()함수와 notify()함수, notifyAll()함수를 사용한다. 배타 동기를 지정하는 함수들은 공통 자원을 사용하고 있는 경우이다. 공통 자원을 사용할 경우 배타 동기를 선언하는 synchronized라는 키워드를 적어주기만 하면 상호배타의 원리를 만족시키는 함수로 만들어준다. 조건 동기의 경우 wait()함수를 실행하면 진입한 쓰레드를 조건 동기 queue에 블록을 시킨다. notify()함수는 그렇게 블록된 함수를 깨우는데 새로운 쓰레드가 실행하는 방식으로 깨우게 된다. notifyAll()은 모든 쓰레드를 깨우는 것으로 사용할 수 있다.
세마포의 경우와 비교를 해볼 수 있다. 세마포의 경우 임계구역 앞에 설치되어 초기 값을 설정해 들어갈 수 있는 한계를 놓는다. 들어갈 때 acquire()명령하고 나올 때는 release()명령을 실행시켜 주어야한다. 하지만 이런 관계를 기억하는 것이 힘들다. 이와 반대로 모니터는 따로 명령을 불러줄 필요 없이 함수에 synchronized만 붙여 넣으면 상호배타의 기능을 수행할 수 있다.
은행계좌 문제의 자바 프로그램을 예시로 들어보자. 우리는 앞에서 세마포를 이용해서 은행계좌 문제를 하였는데 지금은 모니터를 바로 사용해 볼 것이다. 은행계좌 문제에서 은행계좌에 대한 값이 공통 자원으로 사용되며 이에 접근하는 함수가 입금과 출금이라는 값이 된다. 따라서 우리는 모니터로 만들기 위해서 접근하는 함수 앞에 synchronized를 선언하여 공통 자원에 접근하는 함수이라는 것을 선언한다. 그러면 접근하는 하나의 함수가 실행될 때 다른 synchronized 함수는 실행될 수 없게 된다. 이렇게 되면 다른 쓰레드는 함수로 임계구역에 들어갈 수 없게 되어 상호배타가 만족되게 된다.
세마포의 경우 쓰레드의 실행 순서를 사용자 마음대로 할 수 있다는 장점이 있었다. 모니터 역시 가능하다. notify()함수와 wait()함수를 이용하면 모니터에서도 순서를 제어할 수 있다. 프로세스1과 프로세스2에 대해서 프로세스1을 먼저 실행시키고 싶다고 가정하자. 그러면 프로세스2의 실행코드 전에 wait()함수를 기술해주면 프로세스2는 임계구역에서 실행 코드를 실행시키기 전에 wait()함수에 의해 조건 동기의 queue에 블록이 되게 된다. 그러면 문맥전환에 의해 프로세스1에 실행 권한이 넘어가게 되고 임계구역에 들어가서 실행코드를 실행시킨다. 실행이 끝나고 난 후 notify()함수를 실행시켜 프로세스2를 깨어나게 하여 임계구역에 접근을 하도록 한다. 이러면 우리는 항상 프로세스1이 프로세스2보다 먼저 실행이 되도록 프로그램을 만들 수 있다.
출처 http://copycode.tistory.com/83
A Monitor is an object designed to be accessed from multiple threads. The member functions or methods of a monitor object will enforce mutual exclusion, so only one thread may be performing any action on the object at a given time. If one thread is currently executing a member function of the object then any other thread that tries to call a member function of that object will have to wait until the first has finished.
A Semaphore is a lower-level object. You might well use a semaphore to implement a monitor. A semaphore essentially is just a counter. When the counter is positive, if a thread tries to acquire the semaphore then it is allowed, and the counter is decremented. When a thread is done then it releases the semaphore, and increments the counter.
If the counter is already zero when a thread tries to acquire the semaphore then it has to wait until another thread releases the semaphore. If multiple threads are waiting when a thread releases a semaphore then one of them gets it. The thread that releases a semaphore need not be the same thread that acquired it.
A monitor is like a public toilet. Only one person can enter at a time. They lock the door to prevent anyone else coming in, do their stuff, and then unlock it when they leave.
A semaphore is like a bike hire place. They have a certain number of bikes. If you try and hire a bike and they have one free then you can take it, otherwise you must wait. When someone returns their bike then someone else can take it. If you have a bike then you can give it to someone else to return --- the bike hire place doesn't care who returns it, as long as they get their bike back.
Following explanation actually explains how wait() and signal() of monitor differ from P and V of semaphore.
The wait() and signal() operations on condition variables in a monitor are similar to P and Voperations on counting semaphores.
A wait statement can block a process's execution, while a signal statement can cause another process to be unblocked. However, there are some differences between them. When a process executes a P operation, it does not necessarily block that process because the counting semaphore may be greater than zero. In contrast, when a wait statement is executed, it always blocks the process. When a task executes a V operation on a semaphore, it either unblocks a task waiting on that semaphore or increments the semaphore counter if there is no task to unlock. On the other hand, if a process executes a signal statement when there is no other process to unblock, there is no effect on the condition variable. Another difference between semaphores and monitors is that users awaken by a V operation can resume execution without delay. Contrarily, users awaken by a signal operation are restarted only when the monitor is unlocked. In addition, a monitor solution is more structured than the one with semaphores because the data and procedures are encapsulated in a single module and that the mutual exclusion is provided automatically by the implementation.
모니터와 세마포어
데이터 손상을 비롯한 문제를 피하려면 애플리케이션에서 스레드와 공유 자원 사이의 상호작용을 제어해야 하며, 이를 스레드 동기화 라고 부른다. 스레드 동기화에 있어서 가장 근본적인 구조로 모니터와 세마포어를 들 수 있다. 이 중 어느 것을 쓸지는 시스템이나 언어에서 무엇을 지원하는 지에 달려 있다.
상호 배제 락에 의해 보호되는 일련의 루틴을 모니터라고 부른다. 락을 획득하기 정까지는 스레드에서 모니터에 속하는 어떤 루틴도 실행시킬 수 없기 때문에 한 번에 한 스레드만 모니터 내부에서 실행 될 수 있다. 다른 스레드는 모드 현재 실행중인 스레드에서 락에대한 제어권을 내놓을 때 까지 기다려야 한다. 어떤 스레드가 모니터 내에서 자신을 중단시키고 어떤 이벤트가 일어나기를 기다리게 되면 다른 스레드가 모니터에 들어갈 수 있다. 나중에 중단된 스레드에서 기다리고 있던 이벤트가 발생했다는 통지를 받으면 다시 일어나서 최대한 빨리 락을 재획득 할 수 있다.
세마포어는 더 간단한 구조로 공유 자원을 보호하는 락이다. 공유자원을 사용하려면 락을 획득해야만 한다. 락을 소유하고 있는 스레드에서 락을 해제하기 전에는 다른 어떤 스레드에서도 그 자원을 사용할 수 없으며, 락이 해제되면 대기중인 스레드가 그 락을 획득하고 대기상태에서 벗어난다. 방금 설명한 것은 가장 기본적인 유형의 세마포어인 상호배제 세마포어이다. 카운팅 세마포어나 이벤트 세마포어같은 다른 유형의 세마포어도 있지만 거의 같은 방식으로 돌아간다.
모리터와 세마포어는 결국 비슷하지만, 사용하기는 모니터쪽이 던 간단한다. 락 획득 및 해제와 관련된 모든 자세한 내용을 다 처리해주기 때문이다. 세마포어를 사용할 때는 애플리케이션에서 스레드가 종료될 때 락을 해제하는 부분에 주의를 기울여야 한다. 그렇지 않으면 그 공유자원을 써야 하는 다른 어떤 스레드도 더 이상 진행을 할 수 없는 상태에 이르게 된다. 그리고 그 공유 자원을 액세스 해야 하는 모든 루틴에서 그 자원을 사용하기 전에 명시적으로 락을 획득해야만 하는데, 코딩하다 보면 가끔 빼먹는 일도 자주 일어난다. 모니터를 사용하는 경우에는 필요한 락을 자동으로 획득하게 된다.
개부분의 시스템에서 정해진 시간 이내에 자원을 획득하지 못하면 시간 초과로 처리하여 오류를 보고한다거나 나중에 재시도 할 수 있는 방법을 제공한다.
물론 공유 자원을 엑세스할 때마다 필요한 락을 획득하는데 시간이 걸리기 때문에 모니터와 세마포어를 사용하는 데에도 시간이 들 수 밖에 없다.
출처 http://dlong.tistory.com/96
The biggest difference between the two is the scope: a mutex's scope is system-wide, whilst monitor's scope depends on the scope of the object you lock on. This means that with monitor, the widest scope you can get is generally application-wide.
So you would mostly use monitor to synchronise between threads running in an application, and use mutex to synchronise between different applications.
출처 https://social.msdn.microsoft.com/Forums/vstudio/en-US/c60e5a8c-42a9-4769-83cc-dc1e50d67994/difference-between-mutex-and-monitor?forum=csharpgeneral
Since you haven't specified which OS or language/library you are talking about, let me answer in a generic way.
Conceptually they are the same. But usually they are implemented slightly differently
Monitor
Usually, the implementation of monitors is faster/light-weight, since it is designed for multi-threaded synchronization within the same process. Also, usually, it is provided by a framework/library itself (as opposed to requesting the OS).
Mutex
Usually, mutexes are provided by the OS kernel and libraries/frameworks simply provide an interface to invoke it. This makes them heavy-weight/slower, but they work across threads on different processes. OS might also provide features to access the mutex by name for easy sharing between instances of separate executables (as opposed to using a handle that can be used by fork
only).
출처https://stackoverflow.com/questions/38159668/monitor-vs-mutex
'운영체제' 카테고리의 다른 글
[운영체제] MMU, page table, inverted page table, TLB (0) | 2018.02.09 |
---|