std::lock
in C++std::lock
is a function template in C++ that provides a way to lock multiple mutex objects simultaneously. It's designed to prevent deadlocks when locking multiple mutexes and is part of the C++ Standard Library's concurrency support.
std::mutex
<mutex>
header#include <iostream>
#include <thread>
#include <mutex>
std::mutex mutex1, mutex2;
void task_a() {
std::lock(mutex1, mutex2);
std::cout << "Task A acquired both locks\n";
mutex1.unlock();
mutex2.unlock();
}
void task_b() {
std::lock(mutex2, mutex1); // Note the different order
std::cout << "Task B acquired both locks\n";
mutex2.unlock();
mutex1.unlock();
}
int main() {
std::thread t1(task_a);
std::thread t2(task_b);
t1.join();
t2.join();
return 0;
}
std::lock
is used to lock both mutexes simultaneously in each task.std::lock
doesn't matter; it prevents deadlocks.std::lock
avoids the circular wait problem.std::lock
with std::unique_lock
#include <iostream>
#include <thread>
#include <mutex>
class Account {
public:
Account(int balance) : balance_(balance) {}
void transfer(Account& to, int amount) {
std::unique_lock<std::mutex> lock_from(mutex_, std::defer_lock);
std::unique_lock<std::mutex> lock_to(to.mutex_, std::defer_lock);
std::lock(lock_from, lock_to);
if (balance_ >= amount) {
balance_ -= amount;
to.balance_ += amount;
std::cout << "Transfer successful\n";
} else {
std::cout << "Insufficient funds\n";
}
}
private:
int balance_;
std::mutex mutex_;
};
int main() {
Account acc1(1000);
Account acc2(500);
std::thread t1(&Account::transfer, &acc1, std::ref(acc2), 300);
std::thread t2(&Account::transfer, &acc2, std::ref(acc1), 200);
t1.join();
t2.join();
return 0;
}
std::unique_lock
is used with std::defer_lock
to create lockable objects without immediately locking.std::lock
is then used to lock both unique_lock
objects simultaneously.std::lock
for deadlock prevention.#include <iostream>
#include <thread>
#include <mutex>
#include <vector>
std::mutex mtx1, mtx2, mtx3, mtx4;
void complex_operation(int id) {
std::vector<std::mutex*> mutexes = {&mtx1, &mtx2, &mtx3, &mtx4};
// Shuffle the order of mutexes to simulate different locking orders
if (id % 2 == 0) {
std::swap(mutexes[0], mutexes[3]);
std::swap(mutexes[1], mutexes[2]);
}
std::lock(*mutexes[0], *mutexes[1], *mutexes[2], *mutexes[3]);
std::cout << "Thread " << id << " acquired all locks\n";
// Unlock in reverse order
mutexes[3]->unlock();
mutexes[2]->unlock();
mutexes[1]->unlock();
mutexes[0]->unlock();
}
int main() {
std::vector<std::thread> threads;
for (int i = 0; i < 4; ++i) {
threads.emplace_back(complex_operation, i);
}
for (auto& t : threads) {
t.join();
}
return 0;
}
std::lock
can take any number of mutex arguments, preventing deadlocks regardless of the order.Exception Safety: If an exception is thrown while std::lock
is acquiring locks, it ensures that any already acquired locks are released.
Performance: While std::lock
prevents deadlocks, it may introduce some overhead compared to manually ordering locks.
Alternatives: For simpler cases, consider using std::scoped_lock
(C++17) which provides similar functionality with RAII semantics.
Unlock Order: When manually unlocking, it's good practice to unlock in the reverse order of acquisition, though not strictly necessary with std::lock
.
Deadlock Prevention: std::lock
uses an unspecified algorithm to prevent deadlocks, which may involve a back-off and retry strategy.
std::lock
is a powerful tool in C++ for safely acquiring multiple locks simultaneously, preventing deadlocks in multi-threaded programs. It's particularly useful in complex scenarios where lock ordering is difficult to manage manually or where the lock order may vary. While it provides strong guarantees against deadlocks, it should be used judiciously, considering performance implications in high-contention scenarios. For most cases, especially in modern C++, wrapper classes like std::unique_lock
or std::scoped_lock
(C++17) provide a more convenient and exception-safe way to use std::lock
's functionality. Understanding and correctly using std::lock
is crucial for writing robust, deadlock-free multi-threaded C++ programs.
[1] https://cplusplus.com/reference/mutex/lock/ [2] https://web.stanford.edu/~ouster/cs111-spring21/lectures/locks/ [3] https://en.cppreference.com/w/cpp/thread/mutex/lock [4] https://stackoverflow.com/questions/18520983/is-stdlock-ill-defined-unimplementable-or-useless [5] https://www.geeksforgeeks.org/std-mutex-in-cpp/
Previous Page | Course Schedule | Course Content