std::unique_lock
The std::unique_lock class provides more flexibility as compared to std::lock_guard. It provides features like manual locking, unlocking, deferred locking, transfer of ownership, and many more to the users. std::unique_lock requires explicit locking and unlocking, it doesn’t automatically acquire and release lock like std::lock_guard. Following is the syntax to use std::unique_lock in C++:
Syntax
std::unique_lock<std::mutex> lock(mutex);
// Mutex is now locked
// Write the Code for Critical section
// Optional: manually unlock before the lock object goes out of scope
lock.unlock();
// Optional: re-lock if needed
lock.lock();
where lock() and unlock() are methods to acquire and release the mutex.
C++ Program using std::unique_lock
The following program illustrates the use of std::unique_lock in C++:
// C++ Program using std::unique_lock
#include <mutex>
#include <thread>
#include <iostream>
using namespace std;
// Global mutex to protect shared_data
mutex mtx;
// Shared data variable
int shared_data = 0;
// Function to increment shared_data
void increment_data() {
// Create a unique_lock object, but defer locking the mutex
unique_lock<mutex> lock(mtx, defer_lock);
// Explicitly acquire the lock
lock.lock();
// Critical section: safely modify shared_data
shared_data += 2;
// Manually release the lock
lock.unlock();
}
int main() {
// Create two threads that run the increment_data function
thread t1(increment_data);
thread t2(increment_data);
// Wait for both threads to finish
t1.join();
t2.join();
// Output the value of shared_data
cout << "Value of shared variable: " << shared_data;
return 0;
}
Output
Value of shared variable: 4
Time Complexity: O(1)
Auxiliary Space: O(1)
Key Features
Following are some key features of std::unique_lock:
- Flexibility: Can lock and unlock multiple times within its scope.
- Deferred Locking: This can be constructed without locking the mutex immediately.
- Timed Locking: Supports times and try-locking operations.
- Ownership Transfer: It allows transferring mutex ownership to another std::unique_lock.
Usage
Following are the use cases when you should consider using std::unique_lock:
- You need more control over the locking mechanism including ability to lock and unlock manually.
- You need to defer locking or conditionally lock a mutex.
- You require timed locking to prevent blocking indefinitely.
- You need to transfer lock ownership between different scopes or threads.
std::unique_lock or std::lock_guard: Which Is Better?
In C++, to manage access to shared resources, the STL (standard template library) of C++, provides synchronization mechanisms such as std::lock_guard and std::unique_lock. Both are useful for managing mutex but have different features and use cases.
In this article, we will discuss the advantages, disadvantages, differences, and use cases of both std::unique_lock and std::lock_guard in C++