세마포어

강병우·2023년 10월 30일
0

병렬프로그래밍

목록 보기
14/24

Producer-Consumer Synchronization and Semaphore

Busy Waiting은 주어진 순서대로 Critical Section에 접근하기 때문에 성능적으로 별로다.
Mutex는 시스템의 임의의 방식으로 순서가 정해진다(랜덤).

각 스레드에 critical section에 접근하기 위한 순서를 정해줘야 할 필요가 있다.

Mutex의 문제점

각각의 스레드가 n * n 매트릭스를 생성하고, 각 매트릭스에 thread-rank order를 곱하는 것을 하고 싶다. 하지만, 매트릭스 곱하기는 교환법칙이 적용되지 않는다.

결과가 다르게 나올 수도 있다.

또다른 예시로, pthread로 메세지를 보내는 것도 있다.

1번은 2번에게, 2번은 3번에게, 3번은 4번에게 메세지를 보내는 소스코드이다.

이부분이 Busy-Waiting하는 곳인데, 본인의 랭크에 도착하여 메세지가 도착했는지 질의할 것이다. 하지만, 메세지가 도착하는 시간보다 메세지가 도착했는지 질의하는 시간이 더 짧을 확률이 있기 때문에, 메세지를 확인하지 않고 바로 else문을 통해 나가버릴 수도 있다.

해결방법 1

이전 코드는 한번만 질의하고 나가버리기 때문에, 메세지의 도착을 기다리지 않는 단점이 있다. 그러면, Null이 아닐 때까지 즉, 메세지가 도착할 때까지 while로 질의를 계속 보내는 것이다. while에서 계속 체크하기 때문에 CPU 자원을 낭비하게 되는 결과가 나타날 수 있다.

해결방법 2

Producer-Consumer approach

생산자가 메세지를 보낼 때까지 대기하다, 생산자가 메세지를 보냈다고 신호를 보내면 이를 받아 메세지를 받아오는 방법이 있다.

이를 Mutex를 사용하여 구현할 수 있다.

하지만, 7번에 진입했을 때, 다른 스레드가 메세지를 보내지 않은 상태일경우 빈 값을 보낼 수도 있다. -> Mutex만으로 문제를 해결할 수 없다!

Semaphore

sem_post함수는 critical section에 진입한 후 세마포어 값을 증가시킨다.
sem_wait세마포어가 0이면 스레드가 블록된다. 0이 아니라면, 세마포어를 감소시킨다음 critical section을 실행시키게 된다. -> 0이 아니라면 진입할 수 있고, 0이라면 진입할 수 없다. 일종의 열쇠 개수라고 보면 된다!

위처럼 코드를 작성할 수 있다.

0개의 댓글