std:: lock
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
헤더 파일에 정의됨
<mutex>
|
||
|
template
<
class
Lockable1,
class
Lockable2,
class
...
LockableN
>
void lock ( Lockable1 & lock1, Lockable2 & lock2, LockableN & ... lockn ) ; |
(C++11 이후) | |
주어진
Lockable
객체들
lock1
,
lock2
,
...
,
lockn
을 데드락을 피하기 위해 데드락 회피 알고리즘을 사용하여 잠급니다.
객체들은 지정되지 않은 일련의
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 + " has lunch partners: "; 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_partner에 대한 다른 호출들이 데드락을 발생시키고 있습니다 { 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); // 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.lunch_partners.push_back(e2.id); e2.lunch_partners.push_back(e1.id); } send_mail(e1, e2); send_mail(e2, e1); } int main() { Employee alice("Alice"), bob("밥"), christina("크리스티나"), dave("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.output() << '\n' << bob.output() << '\n' << christina.output() << '\n' << dave.output() << '\n'; }
가능한 출력:
Alice와 Bob이 락을 기다리고 있습니다 Alice와 Bob이 락을 획득했습니다 Christina와 Bob이 락을 기다리고 있습니다 Christina와 Bob이 락을 획득했습니다 Christina와 Alice가 락을 기다리고 있습니다 Dave와 Bob이 락을 기다리고 있습니다 Dave와 Bob이 락을 획득했습니다 Christina와 Alice가 락을 획득했습니다 직원 Alice의 점심 식사 파트너: Bob, Christina 직원 Bob의 점심 식사 파트너: Alice, Christina, Dave 직원 Christina의 점심 식사 파트너: Bob, Alice 직원 Dave의 점심 식사 파트너: Bob
참고 항목
|
(C++11)
|
이동 가능한 뮤텍스 소유권 래퍼를 구현함
(클래스 템플릿) |
|
(C++11)
|
try_lock
호출을 반복하여 뮤텍스 소유권 획득 시도
(함수 템플릿) |
|
(C++17)
|
데드락 방지 다중 뮤텍스 RAII 래퍼
(클래스 템플릿) |