Java에서 뮤텍스와 세마포어는 무엇입니까? 주요 차이점은 무엇입니까?


답변:


115

세마포는 계산할 수 있지만 뮤텍스는 1까지만 계산할 수 있습니다.

클라이언트 연결을 허용하는 스레드가 실행 중이라고 가정합니다. 이 스레드는 10 개의 클라이언트를 동시에 처리 할 수 ​​있습니다. 그런 다음 각 새 클라이언트는 10에 도달 할 때까지 세마포를 설정합니다. 세마포에 10 개의 플래그가 있으면 스레드가 새 연결을 수락하지 않습니다.

뮤텍스는 일반적으로 물건을 보호하는 데 사용됩니다. 10 명의 클라이언트가 시스템의 여러 부분에 액세스 할 수 있다고 가정합니다. 그런 다음 뮤텍스를 사용하여 시스템의 일부를 보호 할 수 있으므로 한 클라이언트가 해당 하위 시스템에 연결되면 다른 사람이 액세스 할 수 없습니다. 이 목적으로도 Semaphore를 사용할 수 있습니다. 뮤텍스는 "Mutual Exclusion Semaphore" 입니다.


4
이것은 사실이 아닙니다. 동일한 스레드가 동일한 뮤텍스에 두 번 이상 들어갈 수 있으므로 항목`& exit가 균형을 이루도록하기 위해 개수를 유지해야합니다.
finnw

1
@finnw, 일반적으로 뮤텍스에는 재귀와 비 재귀의 두 가지 유형이 있습니다. Java는 기본적으로 재귀 유형을 사용합니까?
edA-qa mort-ora-y 2011

2
@ edA-qa mort-ora-y, "Mutex"라는 용어는 Java VM 또는 API 사양에서 사용되지 않으므로 모든 개체에 내장 된 모니터를 지칭한다고 가정합니다. 이는 Mutex라고하는 Win32 개체와도 유사합니다. . 동일은에 적용됩니다 ReentrantLock. 이들 모두는 재귀 적입니다. 비재 귀적 뮤텍스의 "실제"예를 알지 못하기 때문에 (교과서에서만 보았습니다) 고려하지 않았습니다.
finnw 2014

2
비 재귀 뮤텍스는 카운트 1이있는 세마포어를 사용하여 구현할 수 있습니다. 재귀 호출을 방지하려는 경우 유용 할 수 있습니다. 이것은 실질적인 용도를 가지고 있으며, 개인적으로 큰 프로젝트에서 초기화 코드의 루프를 감지하기 위해 사용했습니다 (A는 A를 다시 초기화하려고하는 B를 초기화합니다).
Alexander Torstling 2011

1
C ++ 11 (C ++ 0x) 표준에서 뮤텍스는 비재 귀적입니다. 그들은 또한 그것을 필요로하는 사람들을 위해 별도의 'recursive_mutex'를 제공합니다. 여기서 Java를 사용하고 있다는 것을 알고 있지만 현재 많은 사람들이 여러 언어로 코드를 작성하고 있습니다.
Aditya Kumar Pandey

139

불행히도 모든 사람들이 세마포어와 뮤텍스 사이의 가장 중요한 차이점을 놓쳤습니다. " 소유권 " 의 개념 .

세마포어에는 소유권 개념이 없습니다. 이는 모든 스레드가 세마포어를 해제 할 수 있음을 의미합니다 (이는 자체적으로 많은 문제를 일으킬 수 있지만 "사망 감지"에 도움이 될 수 있음). 뮤텍스에는 소유권 개념이있는 반면 (즉, 획득 한 뮤텍스 만 해제 할 수 있습니다).
동시 시스템의 안전한 프로그래밍을 위해서는 소유권이 매우 중요합니다. 항상 세마포어보다 뮤텍스를 사용하는 것이 좋습니다 (하지만 성능에 영향이 있음).

뮤텍스는 또한 우선 순위 상속 (우선 순위 반전 문제에 도움이 될 수 있음)과 재귀 (한 가지 유형의 교착 상태 제거)를 지원할 수 있습니다.

또한 "바이너리"세마포어와 "카운팅 / 일반"세마포어가 있음을 지적해야합니다. 자바의 세마포어는 카운팅 세마포어이므로 1보다 큰 값으로 초기화 될 수 있습니다 (하지만 뮤텍스는 개념적으로 1 개만 카운트 할 수 있음). 이것의 유용성은 다른 게시물에서 지적되었습니다.

요약하자면 관리 할 리소스가 여러 개가 아니라면 항상 세마포어보다 뮤텍스를 권장합니다.


1
Feabhas의 대답은 매우 중요합니다. 뮤텍스는 뮤텍스를 해제하려는 스레드가 실제로 소유하고 있는지 확인합니다. 나는 이것을 인터뷰 질문으로 가지고 있었으므로 그것을 기억하려고 노력할 가치가 있습니다.
andrew pate

40

뮤텍스는 기본적으로 상호 배제입니다. 한 번에 하나의 스레드 만 리소스를 얻을 수 있습니다. 한 스레드가 리소스를 획득하면 리소스를 소유 한 스레드가 해제 될 때까지 다른 스레드가 리소스를 획득 할 수 없습니다. 리소스 획득을 기다리는 모든 스레드가 차단됩니다.

세마포어는 실행중인 스레드 수를 제어하는 ​​데 사용됩니다. 고정 된 리소스 세트가 있습니다. 스레드가 동일한 것을 소유 할 때마다 리소스 수가 감소합니다. 세마포어 수가 0에 도달하면 다른 스레드가 리소스를 획득 할 수 없습니다. 스레드는 리소스를 소유 한 다른 스레드가 해제 될 때까지 차단됩니다.

요컨대, 주요 차이점은 한 번에 리소스를 획득 할 수있는 스레드 수입니다.

  • 뮤텍스는 하나입니다.
  • 세마포어-DEFINED_COUNT (세마포어 수만큼)

8

뮤텍스는 리소스에 대한 직렬 액세스에 사용되는 반면 세마포어는 설정된 번호까지 리소스에 대한 액세스를 제한합니다. 뮤텍스는 액세스 수가 1 인 세마포로 생각할 수 있습니다. 세마포어 수를 설정 한 값이 무엇이든간에 스레드는 리소스가 차단되기 전에 리소스에 액세스 할 수 있습니다.



3

뮤텍스는 종종 이진 세마포어로 알려져 있습니다. 0이 아닌 카운트로 세마포어를 만들 수 있지만 뮤텍스는 개념적으로 상위 카운트가 1 인 세마포어입니다.



1

세마포 :

계수 세마포어. 개념적으로 세마포어는 일련의 허가를 유지합니다. 각 acquire()블록은 필요한 경우 허가를받을 수있을 때까지 차단 한 다음 가져옵니다. 각각 release()은 허가를 추가하여 잠재적으로 차단 취득자를 해제합니다. 그러나 실제 허용 개체는 사용되지 않습니다. Semaphore는 사용 가능한 수의 수를 유지하고 그에 따라 작동합니다.

세마포는 종종 일부 (물리적 또는 논리적) 리소스에 액세스 할 수있는 스레드 수를 제한하는 데 사용됩니다.

Java에는 내장 Mutex API가 없습니다. 그러나 바이너리 세마포어로 구현할 수 있습니다.

1로 초기화 된 세마포어는 최대 하나의 허용 만 사용할 수 있도록 사용되며 상호 배제 잠금 역할을 할 수 있습니다. 이것은 두 가지 상태, 즉 사용 가능한 허용 하나 또는 사용 가능한 허용 0 개만 있기 때문에 이진 세마포라고 더 일반적으로 알려져 있습니다.

이러한 방식으로 사용될 때, 바이너리 세마포어는 (많은 Lock 구현과 달리), "lock"이 소유자가 아닌 다른 스레드에 의해 해제 될 수 있다는 속성을 갖습니다 (세마포어에는 소유권 개념이 없기 때문에) . 이것은 교착 상태 복구와 같은 일부 특수 컨텍스트에서 유용 할 수 있습니다.

따라서 Semaphore와 Mutex의 주요 차이점 은 다음과 같습니다.

  1. 세마포어는 허용을 통해 리소스에 액세스하는 스레드 수를 제한합니다. Mutex는 하나의 스레드 만 리소스에 액세스하도록 허용합니다.

  2. 세마포어를 소유 한 스레드가 없습니다. 스레드는 acquire()release()메서드 를 호출 하여 허용 수를 업데이트 할 수 있습니다 . 뮤텍스는 잠금을 유지하는 스레드에 의해서만 잠금 해제되어야합니다.

  3. 뮤텍스가 조건 변수와 함께 사용될 때 함축 된 브라케팅이 있습니다 . 프로그램의 어느 부분이 보호되고 있는지 분명 합니다. d. 이것은 동시 프로그래밍이동 이라고 할 수있는 세마포어의 경우에 반드시 해당되는 것은 아닙니다. 강력하지만 구조화되지 않고 불확실한 방식으로 사용하기에는 너무 쉽습니다.


0

뮤텍스는 이진 세마포어입니다. First Come First Serve 원칙이 충족되도록 1로 초기화해야합니다. 이것은 각 뮤텍스의 다른 특별한 속성을 우리에게 가져다 : 한 사람 아래로 , 않는 것이어야 까지 . Ergo 우리는 일부 자원에 대해 상호 배제를 얻었습니다.

이제 뮤텍스가 일반 세마포어의 특수한 경우임을 알 수 있습니다.


0

동기화 세마포어 의 개체고전적인 신호등을 구현합니다. 신호등은 카운터에서 공유하는 리소스에 대한 액세스를 제어합니다. 카운터가 0보다 크면 액세스가 허용됩니다. 0이면 액세스가 거부됩니다. 카운터는 공유 리소스에 대한 액세스를 허용하는 권한을 계산합니다. 그런 다음 리소스에 액세스하려면 스레드가 신호등에서 권한을 받아야합니다. 일반적으로 신호등을 사용하려면 공유 리소스에 액세스하려는 스레드가 허가를 얻으려고합니다. 신호등 수가 0보다 크면 스레드가 허가를 획득하고 신호등 수가 감소합니다. 그렇지 않으면 스레드가 권한을 얻을 때까지 잠 깁니다. 스레드가 더 이상 공유 리소스에 액세스 할 필요가 없으면 권한을 해제하므로 신호등 수가 증가합니다. 허가를 기다리는 다른 스레드가 있으면 그때 허가를 얻습니다. Java의 Semaphore 클래스는이 메커니즘을 구현합니다.

Semaphore에는 두 가지 빌더가 있습니다.

Semaphore(int num)
Semaphore(int num, boolean come)

num 은 허가의 초기 카운트를 지정합니다. 그런 다음 num은 주어진 시간에 공유 리소스에 액세스 할 수있는 스레드 수를 지정합니다. num이 1이면 한 번에 한 스레드 씩 리소스에 액세스 할 수 있습니다. 설정하여 사실, 당신은 당신을 위해 대기중인 스레드가 요청 된 순서에 따라 권한이 부여되는 것을 보장 할 수 있습니다.


0

비교할 수없는 것을 비교합니다. 기술적으로 세마포어와 뮤텍스 사이에는 의미가 없습니다. Mutex는 응용 프로그램 논리의 모든 이름과 마찬가지로 중요한 이름입니다. 이는 "1"에서 세마포어를 초기화한다는 것을 의미하며 일반적으로 상호 배제를 보장하기 위해 리소스 또는 보호 된 변수를 보호하는 데 사용됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.