답변:
세마포는 계산할 수 있지만 뮤텍스는 1까지만 계산할 수 있습니다.
클라이언트 연결을 허용하는 스레드가 실행 중이라고 가정합니다. 이 스레드는 10 개의 클라이언트를 동시에 처리 할 수 있습니다. 그런 다음 각 새 클라이언트는 10에 도달 할 때까지 세마포를 설정합니다. 세마포에 10 개의 플래그가 있으면 스레드가 새 연결을 수락하지 않습니다.
뮤텍스는 일반적으로 물건을 보호하는 데 사용됩니다. 10 명의 클라이언트가 시스템의 여러 부분에 액세스 할 수 있다고 가정합니다. 그런 다음 뮤텍스를 사용하여 시스템의 일부를 보호 할 수 있으므로 한 클라이언트가 해당 하위 시스템에 연결되면 다른 사람이 액세스 할 수 없습니다. 이 목적으로도 Semaphore를 사용할 수 있습니다. 뮤텍스는 "Mutual Exclusion Semaphore" 입니다.
ReentrantLock
. 이들 모두는 재귀 적입니다. 비재 귀적 뮤텍스의 "실제"예를 알지 못하기 때문에 (교과서에서만 보았습니다) 고려하지 않았습니다.
불행히도 모든 사람들이 세마포어와 뮤텍스 사이의 가장 중요한 차이점을 놓쳤습니다. " 소유권 " 의 개념 .
세마포어에는 소유권 개념이 없습니다. 이는 모든 스레드가 세마포어를 해제 할 수 있음을 의미합니다 (이는 자체적으로 많은 문제를 일으킬 수 있지만 "사망 감지"에 도움이 될 수 있음). 뮤텍스에는 소유권 개념이있는 반면 (즉, 획득 한 뮤텍스 만 해제 할 수 있습니다).
동시 시스템의 안전한 프로그래밍을 위해서는 소유권이 매우 중요합니다. 항상 세마포어보다 뮤텍스를 사용하는 것이 좋습니다 (하지만 성능에 영향이 있음).
뮤텍스는 또한 우선 순위 상속 (우선 순위 반전 문제에 도움이 될 수 있음)과 재귀 (한 가지 유형의 교착 상태 제거)를 지원할 수 있습니다.
또한 "바이너리"세마포어와 "카운팅 / 일반"세마포어가 있음을 지적해야합니다. 자바의 세마포어는 카운팅 세마포어이므로 1보다 큰 값으로 초기화 될 수 있습니다 (하지만 뮤텍스는 개념적으로 1 개만 카운트 할 수 있음). 이것의 유용성은 다른 게시물에서 지적되었습니다.
요약하자면 관리 할 리소스가 여러 개가 아니라면 항상 세마포어보다 뮤텍스를 권장합니다.
뮤텍스는 기본적으로 상호 배제입니다. 한 번에 하나의 스레드 만 리소스를 얻을 수 있습니다. 한 스레드가 리소스를 획득하면 리소스를 소유 한 스레드가 해제 될 때까지 다른 스레드가 리소스를 획득 할 수 없습니다. 리소스 획득을 기다리는 모든 스레드가 차단됩니다.
세마포어는 실행중인 스레드 수를 제어하는 데 사용됩니다. 고정 된 리소스 세트가 있습니다. 스레드가 동일한 것을 소유 할 때마다 리소스 수가 감소합니다. 세마포어 수가 0에 도달하면 다른 스레드가 리소스를 획득 할 수 없습니다. 스레드는 리소스를 소유 한 다른 스레드가 해제 될 때까지 차단됩니다.
요컨대, 주요 차이점은 한 번에 리소스를 획득 할 수있는 스레드 수입니다.
이 질문에는 관련 답변과 공식 Java 지침에 대한 링크 가 있습니다. Java에 Mutex가 있습니까?
세마포 :
계수 세마포어. 개념적으로 세마포어는 일련의 허가를 유지합니다. 각
acquire()
블록은 필요한 경우 허가를받을 수있을 때까지 차단 한 다음 가져옵니다. 각각release()
은 허가를 추가하여 잠재적으로 차단 취득자를 해제합니다. 그러나 실제 허용 개체는 사용되지 않습니다. Semaphore는 사용 가능한 수의 수를 유지하고 그에 따라 작동합니다.
세마포는 종종 일부 (물리적 또는 논리적) 리소스에 액세스 할 수있는 스레드 수를 제한하는 데 사용됩니다.
Java에는 내장 Mutex API가 없습니다. 그러나 바이너리 세마포어로 구현할 수 있습니다.
1로 초기화 된 세마포어는 최대 하나의 허용 만 사용할 수 있도록 사용되며 상호 배제 잠금 역할을 할 수 있습니다. 이것은 두 가지 상태, 즉 사용 가능한 허용 하나 또는 사용 가능한 허용 0 개만 있기 때문에 이진 세마포라고 더 일반적으로 알려져 있습니다.
이러한 방식으로 사용될 때, 바이너리 세마포어는 (많은 Lock 구현과 달리), "lock"이 소유자가 아닌 다른 스레드에 의해 해제 될 수 있다는 속성을 갖습니다 (세마포어에는 소유권 개념이 없기 때문에) . 이것은 교착 상태 복구와 같은 일부 특수 컨텍스트에서 유용 할 수 있습니다.
따라서 Semaphore와 Mutex의 주요 차이점 은 다음과 같습니다.
세마포어는 허용을 통해 리소스에 액세스하는 스레드 수를 제한합니다. Mutex는 하나의 스레드 만 리소스에 액세스하도록 허용합니다.
세마포어를 소유 한 스레드가 없습니다. 스레드는 acquire()
및 release()
메서드 를 호출 하여 허용 수를 업데이트 할 수 있습니다 . 뮤텍스는 잠금을 유지하는 스레드에 의해서만 잠금 해제되어야합니다.
뮤텍스가 조건 변수와 함께 사용될 때 함축 된 브라케팅이 있습니다 . 프로그램의 어느 부분이 보호되고 있는지 분명 합니다. d. 이것은 동시 프로그래밍 의 이동 이라고 할 수있는 세마포어의 경우에 반드시 해당되는 것은 아닙니다. 강력하지만 구조화되지 않고 불확실한 방식으로 사용하기에는 너무 쉽습니다.
동기화 세마포어 의 개체고전적인 신호등을 구현합니다. 신호등은 카운터에서 공유하는 리소스에 대한 액세스를 제어합니다. 카운터가 0보다 크면 액세스가 허용됩니다. 0이면 액세스가 거부됩니다. 카운터는 공유 리소스에 대한 액세스를 허용하는 권한을 계산합니다. 그런 다음 리소스에 액세스하려면 스레드가 신호등에서 권한을 받아야합니다. 일반적으로 신호등을 사용하려면 공유 리소스에 액세스하려는 스레드가 허가를 얻으려고합니다. 신호등 수가 0보다 크면 스레드가 허가를 획득하고 신호등 수가 감소합니다. 그렇지 않으면 스레드가 권한을 얻을 때까지 잠 깁니다. 스레드가 더 이상 공유 리소스에 액세스 할 필요가 없으면 권한을 해제하므로 신호등 수가 증가합니다. 허가를 기다리는 다른 스레드가 있으면 그때 허가를 얻습니다. Java의 Semaphore 클래스는이 메커니즘을 구현합니다.
Semaphore에는 두 가지 빌더가 있습니다.
Semaphore(int num)
Semaphore(int num, boolean come)
num 은 허가의 초기 카운트를 지정합니다. 그런 다음 num은 주어진 시간에 공유 리소스에 액세스 할 수있는 스레드 수를 지정합니다. num이 1이면 한 번에 한 스레드 씩 리소스에 액세스 할 수 있습니다. 설정하여 온 사실, 당신은 당신을 위해 대기중인 스레드가 요청 된 순서에 따라 권한이 부여되는 것을 보장 할 수 있습니다.