Как использовать /create unique_lock в С++?
Пожалуйста, может кто-нибудь объяснить, как использовать и создать уникальный_lock в С++?
Он должен использоваться как для взаимного исключения любой процедуры монитора, так и для выполнения wait() для переменной условия... Я не понимаю из документации, как я должен ее создавать. Нужен мьютекс? Вот псевдокод:
/* 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();
}
Ответы
Ответ 1
std::unique_lock
используйте шаблон RAII.
Если вы хотите заблокировать мьютекс, вы создаете локальную переменную типа std::unique_lock
, передающую параметр mutex в качестве параметра. Когда unique_lock будет построен, он заблокирует мьютекс, и он будет разрушен, он разблокирует мьютекс. Что еще более важно: если выбрано исключение, вызывается std::unique_lock
деструктор , и поэтому мьютекс будет разблокирован.
Пример:
#include<mutex>
int func() {
int a = 3;
{ //Critical session
std::unique_lock<mutex> lock(my_mutex);
some_shared_var += a;
} //End of critical session
}
Ответ 2
Более подробный пример кода с использованием переменных условия:
#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();
}
Ответ 3
std::unique_lock<std::mutex>
содержит блокировку отдельного объекта std::mutex
. Вы связываете объект блокировки с мьютексом, передавая его в конструкторе. Если вы не укажете иное, мьютекс будет немедленно заблокирован. Если объект блокировки удерживает блокировку при ее уничтожении, деструктор освободит блокировку. Как правило, объект std::unique_lock<std::mutex>
будет, таким образом, локальной переменной, объявленной в точке, где вы хотите получить блокировку.
В вашем случае функция produce()
может быть записана следующим образом:
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
}
Обратите внимание, что я заменил if
на while
для учета ложных следов от вызова wait()
.
Ответ 4
В этом случае, я думаю, все, что вам нужно сделать, это:
m.lock();
// Critical section code
m.unlock();