Dans un environnement multithread, il est crucial de garantir que les sections critiques du code sont protégées pour éviter la corruption des données. L’une de ces sections critiques est la gestion des files d’attente de données. Une file d'attente est une structure de données qui suit le principe du « Premier entré, premier sorti » (FIFO). L'implémentation d'une file d'attente thread-safe en C 11 implique l'utilisation de mécanismes de synchronisation tels que des mutex et des variables de condition.
L'extrait de code en question présente une file d'attente thread-safe utilisant std::mutex et std::condition_variable. La méthode enqueue ajoute un élément à la file d'attente tout en maintenant un verrou sur le qMutex pour protéger la file d'attente. Il notifie également tous les threads en attente à l'aide de la variable de condition populatedNotifier.
La méthode dequeue récupère un élément de la file d'attente. Il acquiert un verrou unique sur le qMutex, vérifie si la file d'attente est vide et attend en utilisant la fonction wait_for avec un timeout si nécessaire. Si un fil est informé de nouveaux éléments dans la file d'attente, il quitte l'attente et procède à la récupération et à la suppression d'un élément de la file d'attente.
Cependant, des erreurs de segmentation ont été observées lorsque la file d'attente est vide, indiquant que la fonction wait_for est renvoyée. sans notification. Cela peut se produire en raison d'un réveil parasite.
Pour éviter ce problème, il est conseillé d'inverser la condition de la boucle while. Au lieu d'« attendre que la file d'attente ne soit pas vide », attendez que « la file d'attente soit vide ». Cela garantit que la boucle revérifie le vide de la file d'attente après tout réveil intempestif.
Voici une version révisée de la méthode dequeue :
<code class="cpp">std::string FileQueue::dequeue(const std::chrono::milliseconds& timeout) { std::unique_lock<std::mutex> lock(qMutex); while (q.empty()) { if (populatedNotifier.wait_for(lock, timeout) == std::cv_status::no_timeout) { // Lock may have been released spuriously; recheck condition if (q.empty()) { return std::string(); } std::string ret = q.front(); q.pop(); return ret; } else { return std::string(); } } std::string ret = q.front(); q.pop(); return ret; }</code>
Cela garantit que le thread ne continue que lorsque la file d'attente n'est pas vide, évitant ainsi les erreurs de segmentation causées par des réveils parasites.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!