Comment puis-je obtenir quelque chose de similaire à un sémaphore en utilisant boost en c ++?

J’ai remarqué que le boost ne semble pas supporter les sémaphores. Quel est le moyen le plus simple d’obtenir un effet similaire?

Vous avez besoin des sémaphores Boost Interprocess ou des primitives de synchronisation Boost Thread .

Mutex / Lock et condition sont des primitives couramment utilisées pour synchroniser l’access à des ressources partagées sur plusieurs threads d’un même processus. Il existe des types de mutex exclusifs , lecteurs-écrivains et récursifs / réentrants . En d’autres termes, Mutex est un verrou exclusif. La condition est utilisée pour atteindre l’atomicité lorsque vous devez déverrouiller le mutex et attendre que l’object change. Lorsque vous commencez à attendre une condition, le mutex est déverrouillé et garantit qu’un délocking + appel à l’attente est atomique et qu’aucun autre thread ne peut modifier une ressource entre ces deux opérations.

Sémaphore, dans un autre cas, est un mélange de condition et de mutex et est utilisé exactement dans le même but, mais pour synchroniser l’access entre les processus.

Voir Mutex vs Semaphore .

La synchronisation non bloquante / sans locking est également très répandue. Personnellement, je l’utilise dans des applications de trading haute fréquence lorsque la quantité de données est relativement importante et que la faible latence compte beaucoup.

Dans votre cas, je suppose que 5 philosophes peuvent avoir un dîner dans un processus unique avec 5 discussions. Dans ce cas, vous devez utiliser un mutex, pas un sémaphore. Cependant, vous pouvez ou non utiliser la condition. Cela dépend de quoi et comment exactement vous voulez mettre en œuvre cette procédure.

Je ne sais pas comment mieux le décrire car je finirai par écrire un livre à ce sujet. Je vous recommande donc de trouver un livre déjà écrit pour comprendre les concepts de base. Une fois que vous avez compris les bases, vous pouvez utiliser des API / bibliothèques / frameworks tels que les threads POSIX , Boost Interprocess ou Thread , ACE ou même des algorithmes non bloquants pour atteindre vos objectives.

Bonne chance!

C’est un moyen d’implémenter un sémaphore très simple en utilisant Boost.Thread. C’est un sémaphore inter-thread, et non interprocess. Aucune garantie implicite, etc. – Je n’ai même pas compilé le code. Il illustre les interactions entre les mutex et les variables de condition et suppose une version relativement récente de Boost.

Notez comment le mutex et la variable de condition sont “appariés” – les threads doivent avoir un verrou sur le mutex pour pouvoir attendre la variable de condition et ré-acquérir le verrou lorsqu’ils sont réveillés. En outre, le code qui modifie les données doit explicitement réveiller un autre code en attente. Cela signifie que le mutex, la variable de condition, les données et la ou les conditions qui provoquent le réveil sont tous étroitement couplés. Le couplage étroit signifie également que les données, le mutex et la variable de condition doivent être encapsulés 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.

Tout cela est vraiment destiné à compléter la réponse de Vlad Lazarenko – comprendre la théorie et les principes est au moins aussi important que d’avoir un code “fonctionnel” dans une programmation multithread.

#include  #include  #include  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 lock(mutex_); return count_; } void signal() //called "release" in Java { boost::unique_lock 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 lock(mutex_); while (count_ == 0) { condition_.wait(lock); } --count_; } }; 

J’ai créé une classe de sémaphores compatible avec le concept boosts TimedLockable , qui peut donc être utilisé avec des verrous tels que boost::unique_lock . Ce n’est pas un sémaphore dans une définition classique de l’un, mais peut être utilisé comme tel. Néanmoins, espérons que cela pourra être utile à quelqu’un.

C’est en quelque sorte testé, mais il y a une grande possibilité, que j’ai fait quelque chose de mal. Ce serait génial si quelqu’un pouvait prouver qu’il était correct.

 class semaphore { private: semaphore(const semaphore & other); semaphore & operator = (const semaphore & other); boost::mutex _mutex; boost::condition_variable _condVar; size_t _count; class wait_predicate { private: const size_t & _countRef; public: wait_predicate(const size_t & countRef) : _countRef(countRef) {} bool operator()() { return _countRef > 0; } }; // must be used inside a locked scope! inline wait_predicate getWaitPredicate() const { return wait_predicate(_count); } public: semaphore(size_t size): _count(size) {} void lock() { boost::unique_lock local_lock(_mutex); _condVar.wait(local_lock, getWaitPredicate()); _count--; } void unlock() { boost::unique_lock local_lock(_mutex); _count++; _condVar.notify_one(); } bool try_lock() { boost::unique_lock local_lock(_mutex); if (0 == _count) return false; _count--; return true; } template  bool try_lock_for(const Duration & duration) { boost::unique_lock local_lock(_mutex); if (!_condVar.wait_for(local_lock, duration, getWaitPredicate())) return false; _count--; return true; } template  bool try_lock_until(const TimePoint & timePoint) { boost::unique_lock local_lock(_mutex); if (!_condVar.wait_until(local_lock, timePoint, getWaitPredicate())) return false; _count--; return true; } template  bool timed_lock(const WaitCriteria & criteria) { boost::unique_lock local_lock(_mutex); if (!_condVar.timed_wait(local_lock, criteria, getWaitPredicate())) return false; _count--; return true; } };