CodeBlanks Logo Icon CodeBlanks

std::lock_guard

Learn RAII locking with std::lock_guard.

std::lock_guard

std::lock_guard is an RAII wrapper for a mutex. Its constructor calls lock and its destructor calls unlock. When scope ends the lock is released automatically. The syntax is std::lock_guard<std::mutex> lk(m);.

This prevents forgetting to call lock and unlock. Especially when an exception is thrown the lock still releases because the destructor always runs. lock_guard has only a constructor and destructor; it does not support move or copy. It is ideal for simple, safe critical section management.

Exception safety

The main strength of lock_guard is releasing the lock even when an exception is thrown. With m.lock();, a subsequent throw would skip unlock; the lock would stay forever. lock_guard removes this problem.

This is a typical example of RAII (Resource Acquisition Is Initialization). A resource (lock) is tied to an object's lifetime; when the object dies the resource is released automatically. In modern C++ std::unique_ptr, std::fstream and std::lock_guard follow this principle.

Practice lock_guard counter

Declare global int counter = 0; and std::mutex m;. Write void add_once() whose body is std::lock_guard<std::mutex> lk(m); counter++;. In main start two threads, join both, then write std::cout << counter;.

Starter code

main.cpp
#include <iostream>
#include <thread>
#include <mutex>

int counter = 0;
std::mutex m;

// Write the add_once function

int main() {
    // Start two threads, wait, print
    return 0;
}

Sample solution

main.cpp
#include <iostream>
#include <thread>
#include <mutex>

int counter = 0;
std::mutex m;

void add_once() {
    std::lock_guard<std::mutex> lk(m);
    counter++;
}

int main() {
    std::thread t1(add_once);
    std::thread t2(add_once);
    t1.join();
    t2.join();
    std::cout << counter;
    return 0;
}

Expected output

2

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 When does lock_guard release the lock?

  • When scope ends Correct answer
  • At program end
  • When unlock is called explicitly
  • When the thread sleeps

Explanation: lock_guard releases the lock via its destructor at scope end.

2 Match each expression to its role

Term Meaning
std::lock_guard<std::mutex> lk(m) RAII wrapper
lk constructor Calls lock
lk destructor Calls unlock
{ ... } Scope end

3 Complete the lock_guard line

Question
void add_once() {
    std::____<std::mutex> lk(m);
    counter++;
}
Answer
void add_once() {
    std::lock_guard<std::mutex> lk(m);
    counter++;
}

Explanation: std::lock_guard<std::mutex> lk(m); acquires the lock with RAII.

All lessons in Advanced