2017-04-24 4 views
0

Considérez le code suivant snippetpourquoi les attend condition_variable indéfiniment

#include <future> 

std::mutex asyncMut_; 
std::atomic<bool> isAsyncOperAllowed = false; 
std::condition_variable cv; 

void asyncFunc() 
{ 
    while (isAsyncOperAllowed) 
    { 
     std::unique_lock<std::mutex> ul(asyncMut_); 
     cv.wait(ul, []() 
     { 
      return isAsyncOperAllowed == false; 
     }); 
    } 
} 

int main() 
{ 
    isAsyncOperAllowed = true; 
    auto fut = std::async(std::launch::async, asyncFunc); 

    std::this_thread::sleep_for(std::chrono::seconds(3)); 

    std::lock_guard<std::mutex> lg(asyncMut_); 
    isAsyncOperAllowed = false; 
    cv.notify_one(); 

    fut.get(); 
} 

J'attends qu'une fois que je change l'état de la variable isAsyncOperAllowed et avisez la variable d'état, la variable d'état à l'intérieur du asyncFunc doit quitter l'attente et asyncFync devrait retourner et le principal devrait se terminer.

J'observe que la variable de condition continue d'attendre indéfiniment. Qu'est-ce que je fais mal?

P.S. Je suis sur Win10 - VS2015

+1

aussi en C++ vous n'avez pas besoin d'envelopper le 'cv.wait (ul, []() {...})' l'intérieur d'une boucle pour gérer sillages parasites. La bibliothèque effectue la boucle sur le prédicat pour vous. Si vous utilisez la surcharge de 'wait()' qui ne prend pas de prédicat, vous aurez besoin de la boucle 'while', comme si vous utilisiez l'interface pthreads de l'API C pour les variables de condition. –

Répondre

2

Deadlock: main() débloque jamais lg si bien que le cv à asyncFunc() est notifié, il obtient jamais une occasion de courir, car il ne peut prétendre la serrure.

Essayez:

int main() 
{ 
    isAsyncOperAllowed = true; 
    auto fut = std::async(std::launch::async, asyncFunc); 

    std::this_thread::sleep_for(std::chrono::seconds(3)); 

    { 
     std::lock_guard<std::mutex> lg(asyncMut_); 
     isAsyncOperAllowed = false; 
    } 
    cv.notify_one(); 

    fut.get(); 
}