명확해야 함 : 대부분 임베디드 작업을 수행합니다. 즉, 마이크로 컨트롤러에서 C 및 일종의 실시간 커널입니다. 실제로이 질문은 플랫폼 독립적이어야합니다.카운팅 세마포의 사용 사례
저는 Michael Barr : Mutexes and Semaphores Demystified의 멋진 기사와이 related answer on StackOverflow을 읽었습니다. 바이너리 세마포어가 무엇인지, 뮤텍스가 무엇인지 명확히 이해하고 있습니다. 훌륭합니다.
솔직히 말하면 나는 소위 카운팅 세마포어 (semaphore) (즉, 최대 카운트가 1보다 큰 세마포어)가 무엇인지를 결코 알지 못하고 여전히 이해할 수 없습니다. 어떤 경우에 사용해야합니까?
필자는 전에 Michael Barr의 기사를 읽기 전에 "과 같은 말을했습니다. 특정 침대 수의 호텔 방이있을 때 사용할 수 있습니다. 침대 수 그 방의 키 숫자와 마찬가지로 세마포어의 최대 값입니다. "".
아마도 멋지게 들리 겠지만 프로그래밍 실습에서는 이러한 상황을 결코 경험할 수 없었습니다. (그리고 상상할 수도없는) Michael Barr는 이러한 접근 방식이 잘못되었다고 생각합니다.
그런 다음 필자가이 기사를 읽은 후, 일종의 FIFO 버퍼가있을 때 아마도 사용했을 것으로 생각됩니다. 버퍼의 용량이 10 개의 요소라고 가정하고 우리는 A (생산자)와 B (소비자)의 두 가지 작업을 수행합니다. 그 다음 :
- 세마포어의 최대 개수는 10으로 설정해야합니다.
- A가 버퍼에 데이터를 넣으려는 경우,
signal
은 세마포어입니다. - B가 버퍼에서 데이터를 가져 오려면,
wait
은 세마포어입니다.
음,하지만 작동하지 않습니다
- 무엇 A는 FIFO에 새 데이터를 넣어하려고하지만 여지가없는 경우? 장소를 기다리는 방법 : 새 데이터를 입력하기 전에
signal
을 호출해야합니까? (signal
은 최대 카운트 < 최대 카운트까지 기다릴 수 있어야합니다)? 그렇다면, 데이터가 실제로 FIFO에 저장되기 전에 세마포어가 신호를받습니다. 이것은 잘못된 것입니다. - 세마포어는 적절한 동기화에 충분하지 않습니다. FIFO 자체도 동기화되어야합니다. 그런 다음 고전적인 TOCTTOU 문제를 생성합니다. 세마포어가 이미 신호를 받거나 대기하는 동안 시간이 있지만 FIFO가 아직 수정되지 않았습니다.
그럼, 그 짐승을 사용해야 할 때, 카운팅 세마포어를 사용해야합니까?
음, 프로듀서 P1이 '사용 가능'을 기다리고 뮤텍스를 잠그는 순간 사이에 시간이 있습니다. 그래서, 다른 프로듀서 P2가 그 시퀀스를 인터럽트했을 수도 있습니다 (그리고 뮤텍스를 먼저 잠그십시오). 그런 다음 P1은 뮤텍스를 잠그지 만 큐는 이미 가득 차 있습니다. P1은 뮤텍스를 잠금 해제하고 '사용 가능'을 다시 기다려야합니다. 이게 실제로 좋은가요? 그리고 와우 !, 단 하나의 데이터 대기열에 대한 세 개의 객체. 내가 사용하는 실시간 커널 (TNeoKernel : https://bitbucket.org/dfrank/tneokernel)은 atomic wait-and-put-data와 원자 적 wait-and-get-data 연산을 제공하는 데이터 큐를 제공합니다. –
음, 프로듀서 P1이 'available'을 기다리고 뮤텍스를 잠그는 순간 사이에 시간이 있습니다. 그래서 그 시나리오에서 다른 프로듀서 P2가 인터럽트를 중단했다면 (그리고 뮤텍스를 먼저 잠그십시오) '두 스레드가 모두'사용 가능한 '세마포어 단위를 얻었 기 때문에 대기열에 두 개의 공간이 있어야합니다. 쓰레드는 큐를 오버플로하지 않고 객체를 푸시 할 수 있습니다. 사용자가 제안한 실시간 커널 - 모든 수의 생산자/소비자와 블로킹되고 제한된 대기열을 허용합니까? –
또한 '단순 대기열 및 뮤텍스'대신 'lockfree'대기열을 사용할 수 있습니다. lockfree 대기열 클래스가 여러 제작자와 소비자에게 무조건 안전한 한. –