std:: lock
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Определено в заголовке
<mutex>
|
||
|
template
<
class
Lockable1,
class
Lockable2,
class
...
LockableN
>
void lock ( Lockable1 & lock1, Lockable2 & lock2, LockableN & ... lockn ) ; |
(начиная с C++11) | |
Блокирует данные
Lockable
объекты
lock1
,
lock2
,
...
,
lockn
используя алгоритм предотвращения взаимоблокировок для избежания deadlock.
Объекты блокируются с помощью неуказанной последовательности вызовов
lock
,
try_lock
и
unlock
. Если вызов
lock
или
unlock
приводит к исключению,
unlock
вызывается для всех заблокированных объектов перед повторным выбросом исключения.
Содержание |
Параметры
| lock1, lock2, ... , lockn | - | объекты Lockable для блокировки |
Возвращаемое значение
(нет)
Примечания
Boost предоставляет версию этой функции которая принимает последовательность Lockable объектов, определенную парой итераторов.
std::scoped_lock
предоставляет
RAII
обёртку для этой функции и обычно предпочтительнее прямого вызова
std::lock
.
Пример
В следующем примере используется
std::lock
для блокировки пар мьютексов без взаимной блокировки.
#include <chrono> #include <functional> #include <iostream> #include <mutex> #include <string> #include <thread> #include <vector> struct Employee { Employee(std::string id) : id(id) {} std::string id; std::vector<std::string> lunch_partners; std::mutex m; std::string output() const { std::string ret = "Сотрудник " + id + " имеет партнеров по обеду: "; for (auto n{lunch_partners.size()}; const auto& partner : lunch_partners) ret += partner + (--n ? ", " : ""); return ret; } }; void send_mail(Employee&, Employee&) { // Имитация трудоемкой операции обмена сообщениями std::this_thread::sleep_for(std::chrono::milliseconds(696)); } void assign_lunch_partner(Employee& e1, Employee& e2) { static std::mutex io_mutex; { std::lock_guard<std::mutex> lk(io_mutex); std::cout << e1.id << " и " << e2.id << " ожидают блокировок" << std::endl; } // Используйте std::lock для получения двух блокировок без опасений о // другие вызовы assign_lunch_partrier блокируют нас { std::lock(e1.m, e2.m); std::lock_guard<std::mutex> lk1(e1.m, std::adopt_lock); std::lock_guard<std::mutex> lk2(e2.m, std::adopt_lock); // Эквивалентный код (если требуются unique_lock, например, для переменных условий) // std::unique_lock<std::mutex> lk1(e1.m, std::defer_lock); // std::unique_lock<std::mutex> lk2(e2.m, std::defer_lock); // std::lock(lk1, lk2); // Superior solution available in C++17 // std::scoped_lock lk(e1.m, e2.m); { std::lock_guard<std::mutex> lk(io_mutex); std::cout << e1.id << " и " << e2.id << " получил блокировки" << std::endl; } e1.партнеры по обеду.push_back(e2.id); e2.партнеры_по_обеду.push_back(e1.id); } send_mail(e1, e2); send_mail(e2, e1); } int main() { Employee alice("Алиса"), bob("Боб"), christina("Кристина"), dave("Дейв"); // Назначение в параллельных потоках, так как пользователям рассылаются уведомления о назначениях на обед // занимает много времени std::vector<std::thread> threads; threads.emplace_back(assign_lunch_partner, std::ref(alice), std::ref(bob)); threads.emplace_back(assign_lunch_partner, std::ref(christina), std::ref(bob)); threads.emplace_back(assign_lunch_partner, std::ref(christina), std::ref(alice)); threads.emplace_back(assign_lunch_partner, std::ref(dave), std::ref(bob)); for (auto& thread : threads) thread.join(); std::cout << alice.вывод() << '\n' << bob.вывод() << '\n' << christina.вывод() << '\n' << dave.вывод() << '\n'; }
Возможный вывод:
Алиса и Боб ждут блокировок Алиса и Боб получили блокировки Кристина и Боб ждут блокировок Кристина и Боб получили блокировки Кристина и Алиса ждут блокировок Дэйв и Боб ждут блокировок Дэйв и Боб получили блокировки Кристина и Алиса получили блокировки Сотрудник Алиса имеет партнеров по обеду: Боб, Кристина Сотрудник Боб имеет партнеров по обеду: Алиса, Кристина, Дэйв Сотрудник Кристина имеет партнеров по обеду: Боб, Алиса Сотрудник Дэйв имеет партнеров по обеду: Боб
Смотрите также
|
(C++11)
|
реализует перемещаемую обёртку владения мьютексом
(шаблон класса) |
|
(C++11)
|
пытается получить владение мьютексами с помощью повторных вызовов
try_lock
(шаблон функции) |
|
(C++17)
|
RAII-обёртка для нескольких мьютексов, избегающая взаимоблокировок
(шаблон класса) |