Ce face std::lock_guard
std::lock_guard este cea mai simplă și sigură cale de a folosi un mutex. Constructorul apelează lock(), destructorul apelează unlock(). Mutexul este eliberat la ieșirea din bloc, oricum s-ar ieși: normal, cu return sau prin excepție.
Nu poate fi deblocat mai devreme și nu poate fi mutat. Dacă ai nevoie de asta (sau de std::condition_variable), folosește std::unique_lock. Pentru mai multe mutexuri deodată, std::scoped_lock.
Parametri
| Parametru | Descriere |
|---|---|
m |
Mutexul ocupat pe durata blocului. |
Ce returnează
Un obiect care ține mutexul ocupat cât timp există.
Exemple
Exemplul 1: Un cont bancar folosit de mai multe fire
#include <mutex>
#include <print>
#include <thread>
#include <vector>
class Cont {
public:
void depune(int suma) {
std::lock_guard blocare(m_);
sold_ += suma;
}
bool retrage(int suma) {
std::lock_guard blocare(m_);
if (suma > sold_) return false; // mutexul se eliberează și aici
sold_ -= suma;
return true;
}
int sold() {
std::lock_guard blocare(m_);
return sold_;
}
private:
std::mutex m_;
int sold_ = 0;
};
int main() {
Cont c;
std::vector<std::thread> fire;
for (int i = 0; i < 5; ++i) {
fire.emplace_back([&c] {
for (int j = 0; j < 1000; ++j) c.depune(2);
});
}
for (auto& t : fire) t.join();
std::println("Sold: {} lei", c.sold());
std::println("Retragere 20000: {}", c.retrage(20000));
std::println("Retragere 9000: {}, sold {}", c.retrage(9000), c.sold());
}
Rezultat
Sold: 10000 lei
Retragere 20000: false
Retragere 9000: true, sold 1000
Exemplul 2: Eliberare automată la excepție
#include <mutex>
#include <print>
#include <stdexcept>
std::mutex m;
void operatie(bool esueaza) {
std::lock_guard blocare(m);
if (esueaza) throw std::runtime_error("operație eșuată");
}
int main() {
try {
operatie(true);
} catch (const std::exception& e) {
std::println("Eroare: {}", e.what());
}
std::println("Mutexul este liber: {}", m.try_lock());
m.unlock();
}
Rezultat
Eroare: operație eșuată
Mutexul este liber: true
Greșeli frecvente
- Scrii
std::lock_guard<std::mutex>(m);fără nume de variabilă. Se creează un obiect temporar care eliberează mutexul imediat, la finalul instrucțiunii; secțiunea critică nu este protejată. Dă-i mereu un nume.
Comenzi înrudite
std::mutex: Încuietoare pentru date comune: un singur fir de execuție o poate ține la un moment dat.std::unique_lock: Blocare de mutex flexibilă: poate fi eliberată și reluată, amânată, mutată; necesară pentru condition_variable.std::scoped_lock: Ocupă unul sau mai multe mutexuri deodată, fără risc de blocaj reciproc, și le eliberează automat.