Класс shared_mutex
Класс shared_mutex представляет собой мьютекс,
который позволяет нескольким потокам одновременно
получать доступ к данным для чтения, но только одному
потоку разрешает изменять эти данные. Такой режим
работы называется разделяемым доступом (shared access).
Класс shared_mutex находится в заголовочном
файле <shared_mutex> и является частью
пространства имен std.
Класс предоставляет два типа блокировок: эксклюзивную
(исключительную) и разделяемую (общую). Эксклюзивная
блокировка выполняется через методы lock,
try_lock и unlock - при ее захвате
никакой другой поток не может получить доступ к данным.
Разделяемая блокировка выполняется через методы
lock_shared, try_lock_shared и
unlock_shared - при ее захвате другие потоки
также могут захватить разделяемую блокировку, но не
могут захватить эксклюзивную.
Синтаксис
#include <shared_mutex>
std::shared_mutex mtx;
// эксклюзивная блокировка
mtx.lock();
mtx.unlock();
// разделяемая блокировка
mtx.lock_shared();
mtx.unlock_shared();
Пример
Давайте рассмотрим пример, в котором 3 потока
одновременно читают значение переменной, а один поток
изменяет его. Для чтения используется разделяемая
блокировка, для записи - эксклюзивная:
#include <iostream>
#include <shared_mutex>
#include <thread>
#include <vector>
using namespace std;
shared_mutex mtx;
int value = 0;
void reader(int id)
{
shared_lock<shared_mutex> lock(mtx);
cout << "reader " << id << ": " << value << endl;
}
void writer(int newValue)
{
unique_lock<shared_mutex> lock(mtx);
value = newValue;
cout << "writer: " << value << endl;
}
int main()
{
vector<thread> threads;
threads.push_back(thread(reader, 1));
threads.push_back(thread(reader, 2));
threads.push_back(thread(writer, 5));
threads.push_back(thread(reader, 3));
for (auto& t : threads)
{
t.join();
}
return 0;
}
Результат выполнения кода (порядок строк может отличаться из-за многопоточности):
"reader 1: 0"
"reader 2: 0"
"writer: 5"
"reader 3: 5"
Пример
Давайте используем метод try_lock_shared, чтобы
попытаться захватить разделяемую блокировку без
ожидания. Если блокировка уже захвачена другим потоком
эксклюзивно, метод вернет false:
#include <iostream>
#include <shared_mutex>
#include <thread>
using namespace std;
shared_mutex mtx;
int value = 0;
void writer()
{
unique_lock<shared_mutex> lock(mtx);
value = 10;
cout << "writer: " << value << endl;
this_thread::sleep_for(chrono::milliseconds(100));
}
void reader()
{
if (mtx.try_lock_shared())
{
cout << "reader: " << value << endl;
mtx.unlock_shared();
}
else
{
cout << "reader: lock failed" << endl;
}
}
int main()
{
thread t1(writer);
this_thread::sleep_for(chrono::milliseconds(10));
thread t2(reader);
t1.join();
t2.join();
return 0;
}
Результат выполнения кода:
"writer: 10"
"reader: lock failed"
Смотрите также
-
класс
shared_lock,
который управляет разделяемой блокировкой -
класс
unique_lock,
который управляет эксклюзивной блокировкой -
класс
mutex,
который представляет обычный мьютекс -
класс
timed_mutex,
который позволяет захватывать блокировку с таймаутом