Welcome to our deep dive into the world of C++ synchronization! Today, we'll explore the powerful std::unique_lock class. This lock is a crucial tool in multithreaded programming, helping us manage resource access and avoid race conditions.
Let's start with the basics.
std::unique_lock šstd::unique_lock is a class that wraps around an underlying lock, providing a convenient way to acquire, release, and check the lock ownership. The unique part of std::unique_lock is that it ensures exclusive ownership of the lock ā once a std::unique_lock owns a lock, no other std::unique_lock can own it.
Here's a simple example of creating and acquiring a std::unique_lock:
#include <iostream>
#include <thread>
#include <mutex>
std::mutex mtx;
void do_something() {
std::unique_lock<std::mutex> lock(mtx);
// Critical section
std::cout << "Doing something..." << std::endl;
}
int main() {
std::thread t1(do_something);
std::thread t2(do_something);
t1.join();
t2.join();
return 0;
}In this example, we have a std::mutex (mutex for short) called mtx. The function do_something() acquires the lock on mtx using a std::unique_lock. Only one thread can enter the do_something() function at a time, ensuring the safety of the critical section.
What is `std::unique_lock` in C++?
Acquiring a lock with std::unique_lock can be done in two ways:
std::unique_lock is created and provided a lock, it automatically acquires the lock.lock(): If a lock is already owned by another std::unique_lock, calling lock() will block until the lock is acquired.To release a lock, simply destroy the std::unique_lock object or call its unlock() method.
std::unique_lock<std::mutex> lock(mtx);
// Critical section
lock.unlock(); // or let the object destruct when it goes out of scopestd::unique_lock Ownership Transfer š”std::unique_lock supports ownership transfer, which is useful when we want to pass the lock ownership from one std::unique_lock to another. This can be done using the swap() function.
std::unique_lock<std::mutex> lock1(mtx);
std::unique_lock<std::mutex> lock2;
lock1.swap(lock2); // Now lock2 owns the lock, and lock1 is emptystd::unique_lock and Timed Acquisition š”std::unique_lock can also be used for timed lock acquisition using the try_lock_for() and try_lock_until() functions. These functions return immediately, allowing the calling thread to continue execution if the lock cannot be acquired.
std::unique_lock<std::mutex> lock(mtx);
// Lock acquisition for 100 milliseconds
if (!lock.try_lock_for(std::chrono::milliseconds(100))) {
std::cout << "Couldn't acquire lock" << std::endl;
}How can `std::unique_lock` be used for timed lock acquisition?
And that's a wrap for today's lesson on C++ std::unique_lock! Remember, practice makes perfect, so take some time to experiment with this powerful tool in your own projects. Stay tuned for more exciting topics! š š