Trusted answers to developer questions
Trusted Answers to Developer Questions

Related Tags

scoped lock
scoped lock idiom

What is the scoped locking idiom?

Osamah Ahmad

Grokking Modern System Design Interview for Engineers & Managers

Ace your System Design Interview and take your career to the next level. Learn to handle the design of applications like Netflix, Quora, Facebook, Uber, and many more in a 45-min interview. Learn the RESHADED framework for architecting web-scale applications by determining requirements, constraints, and assumptions before diving into a step-by-step design process.

Overview

The scoped lock class is a mutex wrapper that makes owning one or more mutexes for the length of a scoped block easier.

Purpose

Scoped locks lock a mutex when they’re constructed and unlock it when they’re destructed. When the control flow departs a scope, the C++ rules ensure that objects local to the scope being vacated are properly destructed. This implies that utilizing a scoped lock rather than manually executing lock() and unlock() is a good approach. This makes it impossible to not unlock the mutex even accidentally. An example of this is when an exception is triggered between lock() and unlock().

Example

std::scoped_lock combines RAII-style semantics for owning one or more mutexes with the lock avoidance methods used by std::lock. It gives RAII-style semantics for owning one or more mutexes. Mutexes are released in the opposite order from which they were acquired when std::scoped lock is destroyed.

{
    std::scoped_lock lock{_mutex1,_mutex2};
    //do something
}
#include <mutex>
#include <thread>
#include <iostream>
#include <vector>
#include <functional>
#include <chrono>
#include <string>
struct Employee {
Employee(std::string id) : id(id) {}
std::string id;
std::vector<std::string> lunch_partners;
std::mutex m;
std::string output() const
{
std::string ret = "Employee " + id + " has lunch partners: ";
for( const auto& partner : lunch_partners )
ret += partner + " ";
return ret;
}
};
void assign_lunch_partner(Employee &e1, Employee &e2)
{
static std::mutex io_mutex;
{
std::lock_guard<std::mutex> lk(io_mutex);
std::cout << e1.id << " and " << e2.id << " are waiting for locks" << std::endl;
}
{
std::scoped_lock lock(e1.m, e2.m);
{
std::lock_guard<std::mutex> lk(io_mutex);
std::cout << e1.id << " and " << e2.id << " got locks" << std::endl;
}
e1.lunch_partners.push_back(e2.id);
e2.lunch_partners.push_back(e1.id);
}
}
int main()
{
Employee alice("alice"), bob("bob"), christina("christina"), dave("dave");
std::vector<std::thread> threads;
threads.emplace_back(assign_lunch_partner, std::ref(alice), std::ref(bob));
threads.emplace_back(assign_lunch_partner, std::ref(christina), std::ref(bob));
threads.emplace_back(assign_lunch_partner, std::ref(christina), std::ref(alice));
threads.emplace_back(assign_lunch_partner, std::ref(dave), std::ref(bob));
for (auto &thread : threads) thread.join();
std::cout << alice.output() << '\n' << bob.output() << '\n'
<< christina.output() << '\n' << dave.output() << '\n';
}
The scoped locking idiom implementation

Explanation

  • Lines 9 to 21: We create a structure named Employee that returns an employee’s output and their assigned lunch partners.

  • Lines 23 to 41: We create a function named assign_lunch_partner where scoped_lock combines RAII-style semantics for owning two mutexes and locks them.

  • Lines 43 to 56: We create threads that combine the mutexes and assign lunch partners to an employee.

RELATED TAGS

scoped lock
scoped lock idiom

CONTRIBUTOR

Osamah Ahmad
Copyright ©2022 Educative, Inc. All rights reserved

Grokking Modern System Design Interview for Engineers & Managers

Ace your System Design Interview and take your career to the next level. Learn to handle the design of applications like Netflix, Quora, Facebook, Uber, and many more in a 45-min interview. Learn the RESHADED framework for architecting web-scale applications by determining requirements, constraints, and assumptions before diving into a step-by-step design process.

Keep Exploring