내가 std::condition_variable(lock,pred)
의 VC++ 구현을 검토 한 결과, 기본적으로는 다음과 같습니다 : 기본적으로std :: condition_variable에서 가능한 경쟁 조건이 있습니까?
template<class _Predicate>
void wait(unique_lock<mutex>& _Lck, _Predicate _Pred)
{ // wait for signal and test predicate
while (!_Pred())
wait(_Lck);
}
, cond->_get_cv()->wait(cs);
을 (호출 do_wait
호출 _Cnd_wait
호출 알몸 wait
전화 _Cnd_waitX
이 모든이에를 파일 cond.c).
cond->_get_cv()
은 Concurrency::details::stl_condition_variable_interface
을 반환합니다. 우리는 파일 primitives.h
에 가면
, 우리는 윈도우 7 이상에서, 우리는 좋은 오래된는 Win32 CONDITION_VARIABLE
및 wait
전화 __crtSleepConditionVariableSRW
를 포함하는 클래스 stl_condition_variable_win7
있는 것을 알 수있다.
어셈블리 디버그 비트를 사용하면 __crtSleepConditionVariableSRW
은 SleepConditionVariableSRW
함수 포인터를 추출하고 호출합니다.
내가 아는 한, win32 CONDITION_VARIABLE
은 커널 개체가 아니라 사용자 모드 것입니다. 따라서 일부 스레드가이 변수를 알리고 실제로 스레드가 잠자기 상태가 아닌 경우 알림을 잃어 버리면 시간 초과가되거나 다른 스레드가 알림을 알릴 때까지 스레드가 잠자기 상태로 유지됩니다. 작은 프로그램이 실제로 그것을 증명할 수 있습니다. 통지 시점을 놓친 경우 다른 스레드가 알림을 보냈음에도 스레드는 잠자고 있습니다.
내 질문은 다음과 같습니다 :
하나의 스레드가 조건 변수에서 대기하고 조건부가 false를 반환합니다. 그런 다음 위에 설명 된 전체 호출 체인이 발생합니다. 그 시간에 다른 스레드가 환경을 변경하여 술어가 true를 리턴하도록 및이 조건 변수를 알립니다. 우리는 원래 스레드의 술어를 전달했지만 여전히 호출 체인이 매우 길어 SleepConditionVariableSRW
에 들어 가지 않았습니다.
따라서 우리는 조건 변수 과을 통보했지만 조건 변수에 넣는 조건자는 분명히 true를 반환합니다 (알리미가 작성했기 때문에). 조건 변수에서 계속 영원히 차단할 수 있습니다.
어떻게 동작해야합니까? 그것은 일어나기를 기다리는 커다란 못생긴 경쟁 조건처럼 보입니다. 조건 변수를 알리고 술어가 true를 반환하면 스레드가 차단을 해제해야합니다. 그러나 우리가 술어를 확인하고 잠을 자지 못하는 사이에 림보 (limbo)에 있다면 우리는 영원히 차단됩니다. std::condition_variable::wait
은 원자 함수가 아닙니다.
표준이 그것에 대해 무엇을 말하고 실제로 경쟁 조건입니까?
아하, 나는 "공유 변수가 원자 적이라 할지라도 ..."을 놓쳤다. 이것은 내가 염두에 두었던 것이다. –
@DavidHaim : 이것은 cppreference가 제공하는 힌트입니다. 표준은 그 어떤 것도 말하지 않습니다. 'std :: condition_variable' (일반적으로 조건 변수와 마찬가지로)은 대기 및 통지와 뮤텍스를 유지하는 관계를 생성합니다. 이런 식으로 뮤텍스를 취득해야하는 타당한 이유가 있다고 가정합니다. 아니. 그 뮤텍스와 함께해야 할 일은 당신의 사업입니다. 조건 변수가 실제로하는 유일한 것은 뮤텍스를 해제하고 대기 상태 * 원자 적으로 입력하는 것입니다. "조건"부분은 전적으로 귀하에게 달려 있습니다. – conio