답변:
다음은 언제 무엇을 사용해야하는지 기억하는 방법입니다.
세마포어 : 다른 스레드가 깨어나도록 지시 할 때까지 (스레드) 잠자기를 원할 때 세마포어를 사용합니다. 세마포어 '다운'은 한 스레드 (생산자)에서 발생하고 세마포어 '업'(동일한 세마포어)은 다른 스레드 (소비자)에서 발생합니다. 소비자 스레드는 버퍼 슬롯이 비어있는시기를 알 수 있습니다.
뮤텍스 : (스레드) 다른 스레드에서 동시에 실행해서는 안되는 코드를 실행하려는 경우 뮤텍스를 사용합니다. 뮤텍스 '다운'은 한 스레드에서 발생하고 뮤텍스 '업' 은 나중에 동일한 스레드에서 발생 해야합니다 . 예 : 글로벌 연결 목록에서 노드를 삭제하는 경우 노드를 삭제하는 동안 다른 스레드가 포인터를 사용하는 것을 원하지 않습니다. 뮤텍스를 획득하고 노드 삭제 중일 때 다른 스레드가 동일한 뮤텍스를 획득하려고 시도하면 뮤텍스를 해제 할 때까지 휴면 상태가됩니다.
Spinlock : 실제로 뮤텍스를 사용하고 싶지만 스레드가 절전 모드로 전환되지 않을 때 스핀 락 을 사용합니다. 예 : OS 커널 내의 인터럽트 핸들러는 절대 휴면 상태가 아니어야합니다. 그렇다면 시스템이 정지 / 충돌합니다. 인터럽트 처리기에서 전역 적으로 공유되는 연결 목록에 노드를 삽입해야하는 경우 스핀 락을 획득합니다-노드 삽입-스핀 락 해제.
뮤텍스는 세마포어 와 유사 하지만 한 번에 하나의 로커 만 허용하고 소유권 제한이 세마포어보다 더 엄격 할 수 있는 상호 배제 개체 입니다.
이것은 (a) 를 잠근 동일한 스레드에 의해서만 해제 될 수 있어야한다는 요구 사항과 일반 계수 세마포 (1 개 포함)와 동등하다고 생각할 수 있습니다 .
반면 세마포어는 임의의 개수를 가지며 동시에 많은 로커에 의해 잠길 수 있습니다. 그리고 그것을 주장한 동일한 스레드에 의해 릴리스되어야한다는 요구 사항이 없을 수도 있습니다 (그러나 그렇지 않은 경우 할당 된 메모리와 같이 현재 책임이있는 사람을 신중하게 추적해야합니다).
따라서 리소스 인스턴스 (예 : 테이프 드라이브 3 개)가 여러 개있는 경우 개수가 3 인 세마포어를 사용할 수 있습니다.이 값은 보유하고있는 테이프 드라이브를 알려주는 것이 아니라 특정 숫자.
또한 세마포어를 사용하면 단일 로커가 테이프 간 복사와 같이 리소스의 여러 인스턴스를 잠글 수 있습니다. 하나의 리소스 (손상하지 않으려는 메모리 위치)가있는 경우 뮤텍스가 더 적합합니다.
동등한 작업은 다음과 같습니다.
Counting semaphore Mutual exclusion semaphore
-------------------------- --------------------------
Claim/decrease (P) Lock
Release/increase (V) Unlock
곁에 : 세마포어를 주장하고 해제하는 데 사용되는 기괴한 편지에 대해 궁금해 한 적이 있다면 발명가가 네덜란드 사람이기 때문입니다. Probeer te verlagen은 시도하고 감소하는 것을 의미하고 verhogen은 증가하는 것을 의미합니다.
(a) ... 또는 세마포어와는 완전히 다른 것으로 생각할 수 있으며, 거의 항상 다른 용도로 사용하면 더 안전 할 수 있습니다.
뮤텍스 가 카운트 1을 가진 세마포 가 아니라는 것을 이해하는 것이 매우 중요합니다 !
이것이 바이너리 세마포어 (실제로 카운트 1의 세마포어)와 같은 것이있는 이유입니다.
Mutex와 Binary-Semaphore의 차이점은 소유권 원칙입니다.
뮤텍스는 작업에 의해 획득되므로 동일한 작업에 의해 해제되어야합니다. 이를 통해 이진 세마포어 (우연 릴리스, 재귀 교착 상태 및 우선 순위 반전)의 여러 문제를 해결할 수 있습니다.
주의 사항 : 이러한 문제를 해결하는 방법과 방법은 OS 구현에 달려 있습니다.
뮤텍스는 동일한 작업에 의해 해제되어야하므로 작업 동기화에 적합하지 않습니다. 그러나 조건 변수와 결합하면 모든 종류의 ipc 프리미티브를 구축하기위한 매우 강력한 빌딩 블록을 얻을 수 있습니다.
그래서 내 권장 사항은 : 뮤텍스와 조건 변수 (POSIX pthreads와 같은)를 깨끗하게 구현했다면 이것을 사용하십시오.
해결하려는 문제에 정확히 맞는 경우에만 세마포어를 사용하고, 다른 기본 요소를 빌드하지 마십시오 (예 : 세마포어에서 rw-locks, 뮤텍스 및 조건 변수 사용).
많은 오해가있는 뮤텍스와 세마포어가 있습니다. 지금까지 찾은 가장 좋은 설명은이 3 부 문서입니다.
@opaxdiablo 대답은 완전히 정확하지만 두 가지 사용 시나리오가 상당히 다르다는 점을 지적하고 싶습니다. 뮤텍스는 코드의 일부가 동시에 실행되지 않도록 보호하는 데 사용되며, 세마포어는 한 스레드가 다른 스레드가 실행되도록 신호를 보내는 데 사용됩니다.
/* Task 1 */
pthread_mutex_lock(mutex_thing);
// Safely use shared resource
pthread_mutex_unlock(mutex_thing);
/* Task 2 */
pthread_mutex_lock(mutex_thing);
// Safely use shared resource
pthread_mutex_unlock(mutex_thing); // unlock mutex
세마포어 시나리오는 다릅니다.
/* Task 1 - Producer */
sema_post(&sem); // Send the signal
/* Task 2 - Consumer */
sema_wait(&sem); // Wait for signal
자세한 설명 은 http://www.netrino.com/node/202 를 참조하십시오 .
sema_wait
:-) 제 생각에는, 그들이있어 모두 자원에 대한 다른 스레드을 물려 알림이 (매우 중요, 성능 현명한)의 부작용입니다 보호.
You say that the usage pattern of semaphores is to notify threads
스레드 알림에 대한 1 점. 당신은 호출 할 수 있습니다 sem_post
안전하게 신호 처리기 (에서 pubs.opengroup.org/onlinepubs/009695399/functions/... ) 있지만 호출에 사용하지 않는 것이 좋습니다 pthread_mutex_lock
과 pthread_mutex_unlock
(신호 처리기에서 manpages.ubuntu.com/manpages/lucid/man3/... )
"화장실 예제" -http : //pheatt.emporia.edu/courses/2010/cs557f10/hand07/Mutex%20vs_%20Semaphore.htm 참조 :
뮤텍스 :
화장실의 열쇠입니다. 한 사람이 열쇠를 가질 수 있습니다 (화장실 점유). 완료되면 그 사람은 대기열에있는 다음 사람에게 키를 제공 (해제)합니다.
공식적으로 : "뮤텍스는 일반적으로 하나 이상의 스레드에서 동시에 실행할 수없는 재진입 코드 섹션에 대한 액세스를 직렬화하는 데 사용됩니다. 뮤텍스 객체는 제어 된 섹션에 하나의 스레드 만 허용하므로 다른 스레드는 액세스를 시도합니다. 해당 섹션에서 첫 번째 스레드가 종료 될 때까지 대기합니다. " 참조 : Symbian 개발자 라이브러리
(뮤텍스는 실제로 값이 1 인 세마포어입니다.)
신호기:
무료 동일한 변기 키의 수입니다. 예를 들어, 자물쇠와 열쇠가 동일한 화장실이 4 개 있다고 가정 해 보겠습니다. 세마포어 개수 (키 개수)는 처음에 4로 설정되고 (4 개의 화장실 모두 사용 가능), 사람이 들어올 때 개수 값이 감소합니다. 모든 화장실이 가득 찬 경우, 즉. 남은 빈 키가 없으며 세마포어 카운트는 0입니다. 이제 eq. 한 사람이 화장실을 떠나면 세마포어가 1 (무료 키 하나)로 증가하고 대기열에있는 다음 사람에게 제공됩니다.
공식적으로 : "세마포어는 공유 리소스의 동시 사용자 수를 최대 수로 제한합니다. 스레드는 리소스에 대한 액세스를 요청할 수 있으며 (세마포어 감소), 리소스 사용이 완료되었음을 알릴 수 있습니다 (세마포어 증가). " 참조 : Symbian 개발자 라이브러리
엉뚱한 소리를 내지 않으려 고 노력하지만 나 자신을 도울 수 없습니다.
귀하의 질문은 뮤텍스와 세마포어의 차이점은 무엇입니까? 그리고 더 정확한 질문은 '뮤텍스와 세마포어 사이의 관계는 무엇입니까?'입니다.
(나는 그 질문을 추가했을 것이지만, 어떤 지나치게 열성적인 중재자가 차이점과 관계의 차이를 이해하지 않고 중복으로 닫을 것이라고 확신합니다.)
객체 용어에서 우리는 다음을 관찰 할 수 있습니다.
관찰 .1 세마포는 뮤텍스를 포함합니다.
관찰 .2 뮤텍스는 세마포어가 아니고 세마포어는 뮤텍스가 아닙니다.
이진 세마포어라고 불리는 뮤텍스 인 것처럼 작동하는 세마포어가 있지만 뮤텍스가 아닙니다.
뮤텍스에서 세마포어를 만드는 데 필요한 Signaling (posix는 해당 이름에 condition_variable을 사용함)이라는 특수 요소가 있습니다. 알림 소스로 생각하십시오. 두 개 이상의 스레드가 동일한 알림 소스에 가입되어 있으면 ONE 또는 ALL에 메시지를 보내 깨울 수 있습니다.
뮤텍스에 의해 보호되는 세마포어와 관련된 하나 이상의 카운터가있을 수 있습니다. 세마포어에 대한 가장 간단한 시나리오는 0 또는 1이 될 수있는 단일 카운터가 있습니다.
몬순 비처럼 혼란이 쏟아지는 곳입니다.
카운터가 0 또는 1 일 수있는 세마포어는 뮤텍스가 아닙니다.
Mutex에는 두 가지 상태 (0,1)와 하나의 소유권 (작업)이 있습니다. 세마포어에는 뮤텍스, 일부 카운터 및 조건 변수가 있습니다.
이제 상상력을 사용하면 카운터 사용과 신호시기의 모든 조합이 한 가지 종류의 세마포어를 만들 수 있습니다.
값이 0 또는 1 인 단일 카운터 및 값이 1이 될 때 신호를 보내고 신호를 기다리는 사람 중 하나를 잠금 해제합니다. == 이진 세마포어
값이 0 ~ N 인 단일 카운터 및 값이 N 미만이 될 때 신호를 보내고 값이 N 일 때 잠금 / 대기 == 세마포어 계산
값이 0 ~ N 인 단일 카운터와 값이 N이 될 때 신호를 보내고, 값이 N보다 작을 때 잠금 / 대기합니다. == Barrier semaphore
이제 귀하의 질문에 언제 무엇을 사용해야합니까? (또는 뮤텍스를 사용할 때와 이진 세마포어를 사용하는 경우가 아닌 올바른 질문 버전 .3. 이진 세마포어가 아닌 것과 비교가 없기 때문에 뮤텍스를 사용하십시오.) 1. 바이너리에서 제공하지 않는 사용자 정의 된 동작을 원할 때 뮤텍스를 사용하십시오. 세마포어 (예 : 스핀 잠금 또는 빠른 잠금 또는 재귀 잠금). 일반적으로 속성을 사용하여 뮤텍스를 사용자 정의 할 수 있지만 세마포를 사용자 정의하는 것은 새 세마포를 작성하는 것에 불과합니다. 2. 가볍거나 더 빠른 기본 요소를 원합니다.
원하는 것이 정확히 제공되면 세마포어를 사용하십시오.
바이너리 세마포어 구현에서 제공하는 내용을 이해하지 못하면 IMHO, 뮤텍스를 사용하십시오.
그리고 마지막으로 너무 의존하기보다는 책을 읽으십시오.
질문은 뮤텍스와 이진 세마포어의 차이 여야한다고 생각합니다.
Mutex = 소유권 잠금 메커니즘이며 잠금을 획득 한 스레드 만 잠금을 해제 할 수 있습니다.
이진 세마포어 = 신호 메커니즘에 가깝고 우선 순위가 높은 다른 스레드는 신호를 보내고 잠금을 취할 수 있습니다.
Mutex는 공유 자원을 보호하는 것입니다.
세마포어는 스레드를 디스패치하는 것입니다.
Mutex :
판매 할 티켓이 있다고 상상해보십시오. 많은 사람들이 티켓을 동시에 구매하는 경우를 시뮬레이션 할 수 있습니다. 각 사람은 티켓을 구매하는 스레드입니다. 분명히 공유 리소스이기 때문에 티켓을 보호하기 위해 뮤텍스를 사용해야합니다.
세마포 :
다음과 같이 계산을해야한다고 상상해보십시오.
c = a + b;
또한 geta()
계산할 함수 a
, 계산할 함수 및 getb()
계산 을 수행 b
하는 함수 getc()
가 필요합니다 c = a + b
.
분명히, 우리는 할 수 없어 c = a + b
하지 않는 geta()
및 getb()
완료되었다.
3 개의 함수가 3 개의 스레드이면 3 개의 스레드를 디스패치해야합니다.
int a, b, c;
void geta()
{
a = calculatea();
semaphore_increase();
}
void getb()
{
b = calculateb();
semaphore_increase();
}
void getc()
{
semaphore_decrease();
semaphore_decrease();
c = a + b;
}
t1 = thread_create(geta);
t2 = thread_create(getb);
t3 = thread_create(getc);
thread_join(t3);
세마포어의 도움으로, 위의 코드는 확인 할 수 t3
그것의 일을 전까지하지 않을 것이다 t1
그리고 t2
자신의 작업을 수행했다.
한마디로, 세마포어는 스레드를 논리적 인 순서로 실행하는 반면 뮤텍스는 공유 리소스를 보호하는 것입니다.
따라서 뮤텍스가 초기 값이 1 인 특수 세마포어라고 항상 말하는 사람이 있어도 동일하지 않습니다. 이와 같이 말할 수도 있지만 다른 경우에 사용된다는 점에 유의하십시오. 할 수 있더라도 하나씩 교체하지 마십시오.
x = getx(); y = gety(); z = x + y;
우리가 할 수 없기 때문에 어떤 이유로, 우리는 세 가지를 할 세 가지 스레드를 사용, 현재 스레드의 순서는 매우 중요 x + y
하지 않는 getx
및 gety
완료. 한마디로, 세마포어는 멀티 스레딩의 실행 순서에 관심을 가질 때 사용됩니다.
x
및 y
다음 계산을 완료 z = x + y
. 나는 자바에 CyclicBarrier
. 또한 모든 s가 완료 될 때까지 mapreduce
할 수 없기 때문에 세마포어 사용 사례 라고 말할 수 있는지 확실 하지 않습니다 . reduce
map
지적했듯이 카운트가 1 인 세마포어는 뮤텍스와 동일한 '바이너리'세마포어와 동일합니다.
내가 사용한 세마포어 수가 1보다 큰 세마포어를 본 주요 것은 특정 고정 크기의 대기열이있는 생산자 / 소비자 상황입니다.
그러면 두 개의 세마포가 있습니다. 첫 번째 세마포어는 초기에 대기열의 항목 수로 설정되고 두 번째 세마포어는 0으로 설정됩니다. 생산자는 첫 번째 세마포어에서 P 작업을 수행하고 대기열에 추가합니다. 두 번째에 V 연산을 수행합니다. 소비자는 두 번째 세마포어에서 P 작업을 수행하고 대기열에서 제거한 다음 첫 번째 세마포어에서 V 작업을 수행합니다.
이러한 방식으로 생산자는 대기열을 채울 때마다 차단되고 소비자는 대기열이 비어있을 때마다 차단됩니다.
이진 세마포어와 뮤텍스는 다릅니다. OS 관점에서 이진 세마포어와 카운팅 세마포어는 동일한 방식으로 구현되며 이진 세마포어는 값 0 또는 1을 가질 수 있습니다.
Mutex- > 중요한 코드 섹션에 대해 상호 배제의 유일한 목적으로 만 사용할 수 있습니다.
세마포어 -> 다양한 문제를 해결하는 데 사용할 수 있습니다. 이진 세마포어는 신호 전달에 사용될 수 있으며 상호 배제 문제도 해결할 수 있습니다. 초기화되면 0 , 그것을 해결 시그널링 문제 및 초기화 할 때 1 , 그것을 해결하는 상호 배제 문제.
리소스 수가 더 많고 동기화가 필요한 경우 카운팅 세마포어를 사용할 수 있습니다.
내 블로그에서 이러한 주제에 대해 자세히 논의했습니다.
https://designpatterns-oo-cplusplus.blogspot.com/2015/07/synchronization-primitives-mutex-and.html