Класс unique_lock
Класс unique_lock представляет собой обертку над мьютексом, которая управляет его блокировкой и разблокировкой в стиле RAII (Resource Acquisition Is Initialization). В отличие от lock_guard, класс unique_lock предоставляет более широкие возможности: он позволяет создавать объект без немедленной блокировки мьютекса, блокировать и разблокировать мьютекс вручную, а также передавать владение блокировкой другому объекту unique_lock. Первым параметром конструктор принимает мьютекс, а вторым (необязательным) - стратегию блокировки, например std::defer_lock, std::try_to_lock или std::adopt_lock.
Синтаксис
std::unique_lock<Mutex> lock(mutex);
std::unique_lock<Mutex> lock(mutex, std::defer_lock);
std::unique_lock<Mutex> lock(mutex, std::try_to_lock);
std::unique_lock<Mutex> lock(mutex, std::adopt_lock);
Пример
Давайте рассмотрим базовый пример использования unique_lock для защиты критической секции:
#include <iostream>
#include <mutex>
#include <thread>
using namespace std;
mutex mtx;
int counter = 0;
void increment()
{
unique_lock<mutex> lock(mtx);
counter++;
cout << "Counter: " << counter << endl;
}
int main()
{
thread t1(increment);
thread t2(increment);
t1.join();
t2.join();
return 0;
}
Результат выполнения кода:
"Counter: 1"
"Counter: 2"
Пример
Давайте используем отложенную блокировку с помощью std::defer_lock и заблокируем мьютекс вручную:
#include <iostream>
#include <mutex>
using namespace std;
int main()
{
mutex mtx;
unique_lock<mutex> lock(mtx, defer_lock);
cout << "Lock owns mutex: " << lock.owns_lock() << endl;
lock.lock();
cout << "Lock owns mutex after lock: " << lock.owns_lock() << endl;
lock.unlock();
cout << "Lock owns mutex after unlock: " << lock.owns_lock() << endl;
return 0;
}
Результат выполнения кода:
"Lock owns mutex: 0"
"Lock owns mutex after lock: 1"
"Lock owns mutex after unlock: 0"
Пример
Давайте передадим владение блокировкой другому объекту unique_lock с помощью перемещения:
#include <iostream>
#include <mutex>
using namespace std;
int main()
{
mutex mtx;
unique_lock<mutex> lock1(mtx);
cout << "lock1 owns mutex: " << lock1.owns_lock() << endl;
unique_lock<mutex> lock2 = move(lock1);
cout << "lock1 owns mutex after move: " << lock1.owns_lock() << endl;
cout << "lock2 owns mutex after move: " << lock2.owns_lock() << endl;
return 0;
}
Результат выполнения кода:
"lock1 owns mutex: 1"
"lock1 owns mutex after move: 0"
"lock2 owns mutex after move: 1"
Смотрите также
-
класс
lock_guard,
который представляет собой более простую RAII-обертку над мьютексом -
класс
mutex,
который является базовым примитивом взаимного исключения -
метод
lock,
который блокирует мьютекс, связанный с unique_lock -
метод
unlock,
который разблокирует мьютекс, связанный с unique_lock