2013-02-05 15 views
19

Proszę, czy ktoś może wyjaśnić, jak używać i stworzyć unique_lock w języku C++? Powinny być używane zarówno do wzajemnego wykluczania się do dowolnej procedury monitora, jak i do oczekiwania() na zmienną warunku ... Nie rozumiem z dokumentacji, w jaki sposób mam ją stworzyć. Czy konieczne jest muteks? Tutaj jest pseudo-code:Jak używać/tworzyć unique_lock w języku 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(); 
} 

Odpowiedz

-2

W tym przypadku, myślę, że wszystko, co musisz zrobić, to:

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

-1 _NIE_ wyjątku bezpieczne. – ildjarn

22

std::unique_lock użyć wzoru RAII.

Aby zablokować muteks, należy utworzyć zmienną lokalną typu std::unique_lock, przekazując muteks jako parametr. Po skonstruowaniu unique_lock zablokuje mutex i zostanie zniszczony, odblokuje mutex. Co ważniejsze: Jeśli zostaną wprowadzone wyjątki, wywołanie zostanie wywołane i muteks zostanie odblokowany.

przykład:

#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> posiada blokadę oddzielnym std::mutex obiektu. Obiekt blokady zostaje skojarzony z muteksem, przekazując go do konstruktora. O ile nie określisz inaczej, muteks zostanie natychmiast zablokowany. Jeśli obiekt blokady przytrzyma zamek, gdy zostanie zniszczony, destruktor zwolni blokadę. Zazwyczaj obiekt std::unique_lock<std::mutex> będzie zatem zmienną lokalną, zadeklarowaną w punkcie, w którym chcesz zdobyć blokadę.

W twoim przypadku, funkcja produce() można zapisać tak:

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 
} 

Zauważ, że ja otrzymuje if z while do odpowiedzialności za fałszywe wznawiana za rozmowy wait().

+0

Masz 'else' bez' if'. –

7

Bardziej szczegółowy Kod próbki za pomocą zmiennych warunek:

#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

jawne odblokowanie jest niepotrzebne. zobacz, jak zachowuje się funkcja unique_lock(). – Prab

+0

@Prab, tak aby dać wyjaśnienie: unique_lock() jest automatycznie zwolniony gdy destruktor jest nazywany co oznacza, że ​​jest bezpieczny i że wyjątek automatycznie odblokowuje po opuszczeniu zakresu. – EliSquared