The std::lock_guard is the simplest RAII mutex lock type offered by the standard library.

On construction, a std::lock_guard can either lock the provided mutex, or adopt the lock of an already locked mutex. The lock will then be freed on destruction.

std::lock_guard isn't mutable or copyable/movable and can only hold a lock on a single mutex.

Compiler Explorer link: https://compiler-explorer.com/z/Ko411Ec3r

#cpp #cplusplus #coding #programming #dailybiteofcpp

Compiler Explorer - C++

struct Counter { int v = 0; std::mutex mux; }; int main() { Counter c; std::vector<std::jthread> runners(5); for (auto& r : runners) // spawn 5 threads r = std::jthread([&c]{ // obtain the lock std::lock_guard lock(c.mux); ++c.v; // safely mutate the state }); // lock released runners.clear(); // join threads // c.v == 5 std::println("c.v == {}", c.v); // Dining philosophers // https://en.wikipedia.org/wiki/Dining_philosophers_problem std::vector<std::mutex> forks(5); std::vector<std::jthread> philosophers(5); for (size_t i = 0; i < 5; ++i) philosophers[i] = std::jthread( [idx = i, &forks] { auto& left = forks[idx]; auto& right = forks[(idx+1)%5]; // Obtain locks on both the left and right fork // without a chance a of deadlock std::lock(left, right); // Adopt the locks by lock_guards std::lock_guard lock1(left, std::adopt_lock); std::lock_guard lock2(right, std::adopt_lock); std::println("Philosopher {} has eaten.", idx); }); // locks released }