J'ai remarqué que Boost ne semble pas supporter des sémaphores. Quel est le moyen le plus simple d'atteindre un effet similaire? P>
3 Réponses :
Vous avez besoin de Boost Interprocess Semaphore ou Boost Sunchronisation de fil < / a> primitives. p>
mutex / Lock et état sont des primitives couramment utilisées pour synchroniser l'accès aux ressources partagées sur plusieurs threads d'un processus unique. Il y a exclusif , lecteurs-écrivain et récursif / Retrant Types de mutexs. MuTex, en d'autres termes, est une serrure exclusive. La condition est utilisée pour atteindre l'atomicité lorsque vous devez déverrouiller le mutex et attendre que l'objet change. Lorsque vous commencez à attendre sur une condition, il déverrouille le mutex et les garanties que le déverrouillage + appelez à attendre est atomique et aucun autre thread ne peut modifier une ressource entre ces deux opérations. P>
Semaphore, sur un autre cas, est un mélange de condition et de mutex, et est utilisé exactement au même but, mais de synchroniser l'accès entre les processus. P>
voir Mutex VS Sempaphore . P>
Il y a aussi une telle chose que Synchronisation non bloquante / sans verrouillage que devient très populaire ces jours-ci. Je l'utilise personnellement dans des applications de trading à haute fréquence lorsque la quantité de données est relativement grande et faible latence importe beaucoup. P>
Dans votre cas, je suppose que 5 philosophes peuvent avoir un dîner à l'intérieur d'un seul processus avec 5 threads. Dans ce cas, vous devez utiliser un mutex, pas un sémaphore. Vous pourriez ou non utiliser la condition cependant. Cela dépend de ce que vous voulez exactement et comment vous souhaitez mettre en œuvre cette procédure de restauration. P>
Je ne sais pas comment le décrire mieux car je finirai par écrire un livre à ce sujet. Je vous recommande donc de trouver un livre qui est déjà écrit pour comprendre les concepts de base. Une fois que vous connaissez les bases, vous pouvez utiliser des API / des bibliothèques / des cadres comme threads POSIX , Boost Interprocess ou thread , ACE ou même Non bloquant algorithmes pour atteindre ce que vous voulez. p>
bonne chance! p>
Donc, juste par curiosité, le nom "Interprocess Semaphore" suggère qu'il est censé être partagé entre les processus plutôt que les threads. Cela implique-t-il que cela coûte des frais généraux supplémentaires au-dessus de ce qu'un sémaphore intréprocrocrocrocien utiliser serait théoriquement? Je ne sais pas comment utiliser facilement des conditions de thread pour des applications telles que la demande de jouets mentionnée dans mon commentaire sur la question.
@Jonderie: D'accord, je pensais pouvoir m'éloigner d'une réponse simple, mais tu m'as eu. J'ai commencé à répondre dans un commentaire mais c'était trop grand avec beaucoup de liens, donc j'ai fini par éditer ma réponse. S'il vous plaît voir la version mise à jour. Merci.
Merci, Vlad. Il est vrai que le problème des philosophes de salle à manger utilise des mutiles sur les fourches adjacentes, mais si vous n'ajoutez pas quelque chose de plus, vous obtenez une impasse. Un moyen standard de résoudre ce problème est de permettre seulement à 4 philosophes de dîner à la fois afin de pouvoir toujours progresser. La voie naturelle d'y parvenir est avec un sémaphore.
@jonderie: Semaphore est un équivalent de la condition mutex + à l'intérieur du processus. Regardez le code de la réponse de Doug, il a eu une idée. Je vous recommanderais de lire un bon livre sur le fil.
Il est vraiment dommage que Pthreads ne fournisse que des mutiles et des variables de condition. Oui, ils sont un ensemble i> ensemble de primitives sur lesquels d'autres primitives peuvent être construites, mais ils ne sont pas le moyen le plus efficace i> de construire ces primitives. Compter le sémaphore et les événements réinstallés sont deux cas d'utilisation très couramment utilisés.
La différence entre le sémaphore et le mutex n'est pas que le sémaphore est la synchronisation des interprocesses, tout en ne le fait pas (votre réponse l'implique). Un mutex est efficacement la même chose qu'un sémaphore binaire (compte 1). De plus, rien ne vous empêche de mettre en œuvre des mutiles interprocesses (en fait, Boost fournit un mutex interprocessé)
C'est une façon de mettre en œuvre un sémaphore très simple en utilisant Boost.thread. C'est un sémaphore inter-thread, pas une interprocession. Aucune garantie implicite, etc. - Je n'ai même pas compilé le code. Il illustre la manière dont les mutiles et les variables de condition interagissent et suppose une version raisonnablement récente de Boost.
remarquez comment la variable Mutex et la variable de condition sont "jumelées" - Les threads doivent avoir une serrure sur le mutex pour attendre la variable de condition et ré-acquérir la serrure quand elles sont réveillées. En outre, le code qui modifie les données nécessaires pour réveiller explicitement un autre code qui pourrait être attendu. Cela signifie que le mutex, la variable de condition, les données et la ou les conditions qui entraînent le réveil, sont toutes étroitement couplées. Le couplage serré signifie également que les données, le mutex et la variable de condition doivent être encapsulées si possible si possible - toute modification externe peut casser le code de manière étrange, y compris des blocages, des réveils manqués et d'autres bugs étranges. P>
Tous Ceci est vraiment destiné à compléter la réponse de Vlad Lazarenko - Comprendre la théorie et les principes sont au moins aussi importants que de "travailler", dans la programmation multi-threadé. P>
#include <boost/thread/condition_variable.hpp> #include <boost/thread/mutex.hpp> #include <boost/thread/lock_types.hpp> class semaphore { //The current semaphore count. unsigned int count_; //mutex_ protects count_. //Any code that reads or writes the count_ data must hold a lock on //the mutex. boost::mutex mutex_; //Code that increments count_ must notify the condition variable. boost::condition_variable condition_; public: explicit semaphore(unsigned int initial_count) : count_(initial_count), mutex_(), condition_() { } unsigned int get_count() //for debugging/testing only { //The "lock" object locks the mutex when it's constructed, //and unlocks it when it's destroyed. boost::unique_lock<boost::mutex> lock(mutex_); return count_; } void signal() //called "release" in Java { boost::unique_lock<boost::mutex> lock(mutex_); ++count_; //Wake up any waiting threads. //Always do this, even if count_ wasn't 0 on entry. //Otherwise, we might not wake up enough waiting threads if we //get a number of signal() calls in a row. condition_.notify_one(); } void wait() //called "acquire" in Java { boost::unique_lock<boost::mutex> lock(mutex_); while (count_ == 0) { condition_.wait(lock); } --count_; } };
Fonctionne comme un charme. Dommage que cela ne fait plus partie de boost elle-même.
+ 1 pour le code. Y a-t-il un point sur le mutex dans le compte? Le comte sera "vieux" quand reçu quand même, n'est-ce pas?
Correct, le compte sera vieux quand retourné. Obtenir le nombre d'un sémaphore pour des raisons autres que le débogage est probablement un bogue dans votre programme.
La pâte pourriez-vous l'utiliser dans un exemple. Je suis confus sur la façon de l'utiliser et de la manière dont il permet d'accéder à plusieurs threads à la fois
J'ai fait une classe de sémaphore compatible avec des boosts Son en quelque sorte testé, mais il y a une grande possibilité que j'ai fait quelque chose de mal. Serait génial si quelqu'un pouvait prouver l'exactitude. P> TimedLockable code> concept, de sorte qu'il peut être utilisé avec des verrous comme
boost :: unique_lock
Pourriez-vous être plus précis sur quel comportement que vous recherchez? Étant donné que les gens ont proposé environ 14 types de sémaphores différents.
En ce moment, quelque chose qui me laissera, par exemple, résoudre le problème du philosophe de salle à manger (avec 5 philosophes) en limitant le nombre de personnes à manger au plus 4. avec des sémaphores, je pouvais simplement définir une valeur initiale de 4 et avoir chaque philosophe attendez sur le sémaphore et le signal lorsque vous avez terminé.