web-dev-qa-db-fra.com

Comment utiliser / créer unique_lock en c ++?

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();
}
30
SagittariusA

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
}        
39
André Puel

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();
}
6
Babra Cunningham

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().

6
Anthony Williams