문제

나는이 흥미로운 단락을 발견했다 스레드 문서를 부스트하십시오 오늘:

void wait(boost::unique_lock<boost::mutex>& lock)

...

효과 : Atomically Call Lock.unlock () 및 현재 스레드를 차단합니다. this-> notify_one () 또는 this-> notify_all ()에 대한 호출로 통지되면 스레드가 차단 해제됩니다. 거시적으로. 스레드가 차단 해제되면 (어떤 이유로 든)는 대기 반품을 요청하기 전에 잠금을 호출하여 잠금을 재확인합니다. 함수가 예외로 종료되면 잠금을 호출하여 잠금 장치가 다시 발생합니다.

그래서 내가 관심있는 것은 "스파이어로"라는 단어의 의미입니다. 스레드가 왜 스퓨리어스 이유로 차단 해제 될까요? 이것을 해결하기 위해 무엇을 할 수 있습니까?

도움이 되었습니까?

해결책

Anthony Williams 의이 기사 특히 상세합니다.

스퓨리어스 깨우기는 예측할 수 없습니다. 그들은 본질적으로 사용자의 관점에서 무작위입니다. 그러나 스레드 라이브러리가 대기 스레드가 알림을 놓치지 않도록 안정적으로 보장 할 수없는 경우 일반적으로 발생합니다. 누락 된 알림은 조건 변수를 쓸모 없게 만들어 주므로 스레드 라이브러리는 위험을 감수하기보다는 대기에서 스레드를 깨우냅니다.

그는 또한 당신이 사용해서는 안된다고 지적합니다 timed_wait 지속 시간이 걸리는 과부하가 발생하며 일반적으로 술어를 취하는 버전을 사용해야합니다.

그것은 초보자의 버그이며 간단한 규칙으로 쉽게 극복하는 버그입니다. 조건 변수로 대기 할 때 항상 루프에서 술어를 확인하십시오. 더 교활한 버그는 timed_wait ()에서 나옵니다.

Vladimir Prus 의이 기사 또한 흥미 롭습니다.

그러나 왜 우리는 while 루프가 필요한가? 우리는 다음을 쓸 수 없습니다.

if (!something_happened)
  c.wait(m);

우리는 할 수 없습니다. 그리고 킬러 이유는 '대기'가 '알림'전화없이 돌아올 수 있기 때문입니다. 그것은 Spurious Wakeup이라고하며 Posix에 의해 명시 적으로 허용됩니다. 기본적으로 '대기'에서 수익은 공유 데이터가 변경되었을 수 있음을 나타내므로 데이터를 다시 평가해야합니다.

좋아요, 왜 이것이 아직 고정되지 않았습니까? 첫 번째 이유는 아무도 그것을 고치기를 원하지 않기 때문입니다. 루프에서 '대기'로 콜을 랩핑하는 것은 다른 몇 가지 이유로 매우 바람직합니다. 그러나 이러한 이유는 설명이 필요하지만, 가짜 웨이크 업은 실패없이 첫해 학생에게 적용 할 수있는 망치입니다.

다른 팁

이 블로그 게시물 Linux의 이유를 제공합니다. futex 신호가 프로세스로 전달 될 때 시스템 통화 반환. 불행히도 그것은 다른 것을 설명하지 않습니다 (실제로 더 많은 정보를 요구하고 있습니다).

그만큼 가짜 깨어있는 Wikipedia 항목 (Posix 전체 개념 인 BTW는 부스트에 국한되지 않는 BTW)도 귀하에게 관심을 가질 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top