Knowledge
상호배제 & 뮤텍스,세마포어,스핀락 개념
Sean-creative
2023. 11. 7. 17:19
👉 상호배제(Mutual Exclusion)
- Mutual - 서로의, Exclusion - 배제
- 주로 병행 프로그래밍, 동시성 제어와 관련이 있으며 특정 프로세스가 공유 자원을 사용 중일 때 다른 프로세스가 이 자원에 접근하지 못하도록 막는 것을 의미합니다.
- 결국은 공유를 하면 안되는 자원(Resource)의 동시 사용을 피하는 방법 중 하나입니다.
- 이는 경쟁 조건을 방지하고 일관된 상태를 유지하는 데 중요합니다.
- 이를 위해 뮤텍스, 세마포어, 모니터 등의 동기화 메커니즘이 사용됩니다.
- 스레드의 경우, 프로세스와 달리 메모리의 Stack 영역을 제외한 부분을 다른 스레드와 공유하는데, 이 부분에서 스레드간 동시 사용을 피하고 싶을 때 주로 사용한다.
- 동시 접근을 막기 위해 프로그래머에 의해 구현된 코드 영역을 임계 구역(Critical Section)이라고 한다.
상호배제를 재미있게 설명한 삽화. Mutex가 지켜주는 덕에, 화장실은 딱 1명만 쓸 수 있다.
👉 뮤텍스 & 세마포어
뮤텍스와 세마포어는 모두 상호배제(mutual exclusion)를 제공하는 동기화 메커니즘입니다. 이 두 가지는 다중 스레드 환경에서 공유 자원에 대한 접근을 제어하고 조정하기 위해 사용됩니다. 그러나 뮤텍스와 세마포어는 서로 다른 방식으로 동작합니다.
- 뮤텍스(Mutex): 특정 코드 영역에 대해 하나의 스레드만 접근할 수 있도록 보호합니다. 즉, 뮤텍스를 사용하면 한 번에 한 스레드만이 보호된 자원에 접근할 수 있습니다.
- 세마포어(Semaphore): 세마포어는 공유 자원에 대한 접근을 제한하는 데 사용되는 카운팅 매커니즘입니다. 세마포어는 특정 리소스에 대한 접근 가능한 스레드 또는 프로세스의 수를 제한합니다. 세마포어는 카운터로 사용되며, 일정 수의 스레드만이 동시에 특정 리소스에 접근할 수 있도록 허용합니다.
두 도구는 다중 스레드 환경에서 경쟁 상태나 잘못된 데이터 접근을 방지하기 위해 사용됩니다. 그러나 뮤텍스는 단일 리소스에 대한 상호 배제를 위해 사용되는 반면, 세마포어는 일정 수의 리소스에 대한 접근을 제어하는 데 사용됩니다.
👉 스핀락
- Busy-waiting: 스핀락을 사용하는 스레드는 자원을 얻기 위해 계속 반복적으로 확인하며 기다립니다. 이러한 방식은 Busy-waiting이라고도 하며, 다른 동기화 메커니즘들이 대기 큐에 대기하는 것과는 달리, 자원이 사용 가능해질 때까지 기다립니다.
- 짧은 임계 구역: 스핀락은 임계 구역이 짧은 경우에 유용합니다. 만약 자원을 기다리는 시간이 다른 동기화 메커니즘을 사용하는 것보다 짧다면, 스핀락은 더 효율적일 수 있습니다.
그러나 스핀락은 자원을 기다리는 동안 프로세서를 계속 점유하고 있기 때문에, 자원을 기다리는 시간이 길어질 경우에는 비효율적일 수 있습니다. 따라서 스핀락은 주로 임계 구역이 짧을 때 또는 대기 시간이 예상되는 경우에 사용됩니다.
👉 뮤텍스 그림
- 뮤텍스는 화장실이 하나 밖에 없는 식당과 비슷합니다. 화장실을 가기 위해서는 카운터에서 열쇠를 받아 가야 하며 당신이 화장실을 가려고 하는데 카운터에 키가 있으면 화장실에 사람이 없다는 뜻이고 당신은 그 열쇠를 이용해 화장실에 들어갈 수 있다고 가정합니다.
- 카운터에 열쇠가 없기 때문에 화장실에 사람이 있다는 뜻이며 화장실을 사용할 수 없습니다. 여자가 나올 때 까지 기다려야 합니다.
- 곧이어 다른 사람도 화장실에 가려고 카운터에 대기하고 있습니다. 앞사람이 화장실에서 나와 카운터에 키를 돌려놓았습니다. 이제 기다리던 사람들 중 맨 앞에 있던 사람이 키를 받아 화장실에 갈 수 있습니다.
- 이것이 뮤텍스가 동작하는 방식입니다. 화장실을 이용하는 사람은 프로세스 혹은 쓰레드이며 화장실은 공유자원, 화장실 키는 공유자원에 접근하기 위해 필요한 어떤 오브젝트입니다. 즉, 뮤텍스는 Key에 해당하는 어떤 오브젝트가 있으며 이 오브젝트를 소유한 (쓰레드,프로세스) 만이 공유자원에 접근할 수 있습니다.
👉 세마포어 그림
- 세마포어는 손님이 화장실을 좀 더 쉽게 이용할 수 있는 레스토랑입니다. 세마포어를 이용하는 레스토랑의 화장실에는 여러 개의 칸이 있고 화장실 입구에는 현재 화장실의 빈 칸 개수를 보여주는 전광판이 있다고 가정합니다.
- 만약 당신이 화장실에 가고 싶다면 입구에서 빈 칸의 개수를 확인하고 빈 칸이 1개 이상이라면 빈칸의 개수를 하나 뺀 다음에 화장실로 입장해야 하며 나올 때 빈 칸의 개수를 하나 더해줍니다.
- 모든 칸에 사람이 들어갔을 경우 빈 칸의 개수는 0이 되며 이때 화장실에 들어가고자 하는 사람이 있다면 빈 칸의 개수가 1 혹은 양수로 바뀔 때까지 기다려야 합니다.
- 이처럼 세마포어는 공통으로 관리하는 하나의 값을 이용해 상호배제를 달성합니다. 세마포어도 아까와 똑같이 화장실이 공유자원이며 사람들이 쓰레드, 프로세스이다. 그리고 화장실 빈칸의 개수는 현재 공유자원에 접근할 수 있는 쓰레드,프로세스의 개수를 나타냅니다.
👉 block == sleep ?
- “대기 큐에 들어가서 block이 된다” = 프로세스나 스레드가 어떤 이벤트가 발생할 때까지 기다리는 동작
- 대기 큐에 들어가게 되면 해당 프로세스나 스레드는 실행을 멈추고 다른 작업을 처리하는 동안 기다리게 됩니다. 이러한 동작은 일반적으로 "sleep"이라고 표현되기도 합니다.
- "sleep"이라는 용어는 일반적으로 프로세스나 스레드가 특정 이벤트를 기다리기 위해 자원을 점유하지 않고 대기하는 상태를 가리킵니다. 예를 들어, 프로세스가 외부 입력을 기다리거나 특정 조건을 충족하기 위해 대기하는 경우 sleep 상태에 들어갑니다.