2013-02-05 11 views
19

Per favore, qualcuno può spiegare come usare e creare un unique_lock in C++? Dovrebbe essere usato sia per ottenere l'esclusione reciproca a qualsiasi procedura del monitor e per essere in grado di eseguire l'attesa() sulla variabile di condizione ... Non capisco dalla documentazione come dovrei crearlo. È necessario un mutex? Ecco una pseudo-codice:Come usare/creare unique_lock in C++?

/* 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(); 
} 

risposta

-2

In questo caso, credo che tutto quello che dovete fare è:

m.lock(); 
// Critical section code 
m.unlock(); 
+10

-1 _NOT_ sicuro rispetto alle eccezioni. – ildjarn

22

std::unique_lock usare il pattern RAII.

Quando si desidera bloccare un mutex, si crea una variabile locale di tipo std::unique_lock passando il mutex come parametro. Quando il unique_lock è costruito bloccherà il mutex, e verrà distrutto, sbloccherà il mutex. Ancora più importante: se viene lanciata un'eccezione, il distruggitore std::unique_lockverrà chiamato e quindi il mutex verrà sbloccato.

Esempio:

#include<mutex> 
int some_shared_var=0; 

int func() { 
    int a = 3; 
    { //Critical session 
     std::unique_lock<std::mutex> lock(my_mutex); 
     some_shared_var += a; 
    } //End of critical session 
}   
4

std::unique_lock<std::mutex> detiene un blocco su un std::mutex oggetto separato. Associare l'oggetto lock con il mutex passandolo nel costruttore. Se non diversamente specificato, il mutex verrà immediatamente bloccato. Se l'oggetto di blocco trattiene il lucchetto quando viene distrutto, il distruttore rilascerà il blocco. In genere, l'oggetto std::unique_lock<std::mutex> sarà quindi una variabile locale, dichiarata nel punto in cui si desidera acquisire il blocco.

Nel tuo caso, la funzione produce() potrebbe scrivere in questo modo:

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 
} 

Si noti che ho sostituito il if con un while per tenere conto di scie spuri dalla chiamata wait().

+0

Hai un 'else' senza un' if'. –

7

Un codice di esempio più dettagliato utilizzando variabili di condizione:

#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(); 
} 
+1

lo sblocco esplicito non è necessario. guarda come si comporta un unique_lock(). – Prab

+0

@Prab, solo per dare la spiegazione: unique_lock() viene rilasciato automaticamente quando viene chiamato il distruttore, il che significa che è eccezionalmente sicuro e che si sblocca automaticamente quando si lascia l'oscilloscopio. – EliSquared