2017-02-17 5 views
0

я небольшие сомнения нити будучи проснулись и недоступность замкапропустил сигнал в C++ 11 переменного состояния

std::mutex mut; 
std::queue<data_chunk> data_queue; 
std::condition_variable data_cond; 

void data_preparation_thread() {  
    while(more_data_to_prepare()) {   
     data_chunk const data=prepare_data();   
     std::lock_guard<std::mutex> lk(mut);   
     data_queue.push(data);      
     data_cond.notify_one(); //mutex is still locked here  
    } 
} 

void data_processing_thread() { 
    while(true) { 
     std::unique_lock<std::mutex> lk(mut); 
     data_cond.wait(lk,[]{return !data_queue.empty();}); //what if lk could not acquire the mutex. 
     data_chunk data=data_queue.front();   
     data_queue.pop();   
     lk.unlock(); 
     process(data); 
     if(is_last_chunk(data)) 
      break; 
    } 

}

В приведенном выше примере data_preparation_thread() помещает данные в очереди и уведомляет и ожидание очереди на condition_variable.

Мой вопрос, если другая нить просыпается и обнаруживает, что связанный мьютекс все еще недоступен, он снова спит. Разве это не состояние пропущенного сигнала?

ответ

4

, если другой поток просыпается и обнаруживает, что связано мьютекс еще не доступен, он спит снова

После того, как она вновь приобретает мьютекс он переходит к проверить состояние.

Уведомление об изменении условий - это, по сути, намек на то, что условие может быть изменено и нуждается в повторной оценке. Может быть spurious wake-ups. Код ожидает, что условие станет истинным, а не сигналом.

3

Существует разница между «спящим» по переменной условия (то есть ожиданием сигнала) и «спящим» на мьютексе (т. Е. В ожидании его блокировки).

Если поток просыпается от ожидания на переменную состояния и мьютекс все еще закрыт, он начинает ожидание мьютекса, пока он не сможет приобрести его, а затем проверить состояние (то есть предикат). Это не то же самое, что ждать снова на конвале, поэтому ничего не было пропущено. Он все еще ждет проверки, является ли условие истинным, чего он не может сделать, пока не получит блокировку мьютекса.

Предполагая, что вы правильно проверяете состояние при пробуждении (это то, что предикат, который вы передаете на condition_variable::wait), то вы не пропустите событие, вызвавшее сигнал.