S'il vous plaît, quelqu'un peut-il expliquer comment utiliser et créer un unique_lock en c ++? Il doit être utilisé à la fois pour obtenir l'exclusion mutuelle de toute procédure du moniteur et pour pouvoir exécuter wait () sur la variable de condition ... Je ne comprends pas dans la documentation comment je suis censé le créer. Faut-il un mutex? Voici un pseudo-code:
/* compile with g++, flags -std=c++0x -lpthread */
#include <condition_variable>
#include <mutex>
#include <thread>
#include <iostream>
#include <string.h>
#include <unistd.h>
class monitorTh {
private:
std::mutex m;
std::condition_variable waitP;
std::condition_variable waitC;
char element[32];
std::unique_lock::unique_lock l;
public:
void produce(char* elemProd) {
l.lock();
if (/*already_present_element*/) {
waitP.wait(l);
}
else {/*produce element*/}
l.unlock();
}
void consume() {
/*something specular*/
}
};
int main(int argc, char* argv[]) {
monitorTh* monitor = new monitorTh();
char prodotto[32] = "oggetto";
std::thread producer([&]() {
monitor->produce(prodotto);
});
std::thread consumer([&]() {
monitor->consume();
});
producer.join();
consumer.join();
}
std::unique_lock
utilisez le modèle RAII .
Lorsque vous souhaitez verrouiller un mutex, vous créez une variable locale de type std::unique_lock
en passant le mutex comme paramètre. Lorsque l'unique_lock est construit, il verrouille le mutex, et s'il est détruit, il déverrouille le mutex. Plus important encore: si une exception est levée, le std::unique_lock
destructer sera appelé et donc le mutex sera déverrouillé.
Exemple:
#include<mutex>
int some_shared_var=0;
int func() {
int a = 3;
{ //Critical section
std::unique_lock<std::mutex> lock(my_mutex);
some_shared_var += a;
} //End of critical section
}
Un exemple de code plus détaillé utilisant des variables de condition:
#include<mutex>
std::mutex(mu); //Global variable or place within class
std::condition_variable condition; //A signal that can be used to communicate between functions
auto MyFunction()->void
{
std::unique_lock<mutex> lock(mu);
//Do Stuff
lock.unlock(); //Unlock the mutex
condition.notify_one(); //Notify MyOtherFunction that this is done
}
auto MyOtherFunction()->void
{
std::unique_lock<mutex> lock(mu);
condition.wait(lock) //Wait for MyFunction to finish, a lambda can be passed also to protects against spurious wake up e.g (lock,[](){return *some condition*})
lock.unlock();
}
std::unique_lock<std::mutex>
Détient un verrou sur un objet std::mutex
Distinct. Vous associez l'objet lock au mutex en le passant dans le constructeur. Sauf indication contraire, le mutex sera immédiatement verrouillé. Si l'objet verrou détient le verrou lorsqu'il est détruit, le destructeur relâche le verrou. Typiquement, l'objet std::unique_lock<std::mutex>
Sera donc une variable locale, déclarée à l'endroit où vous souhaitez acquérir le verrou.
Dans votre cas, la fonction produce()
pourrait s'écrire comme ceci:
void produce(char* elemProd) {
std::unique_lock<std::mutex> lk(m); // lock the mutex
while (/*already_present_element*/) { // condition variable waits may wake spuriously
waitP.wait(lk);
}
{/*produce element*/}
// lk releases the lock when it is destroyed
}
Notez que j'ai remplacé le if
par un while
pour tenir compte des réveils parasites de l'appel wait()
.