Namespaces
Variants

std:: lock

From cppreference.net
Concurrency support library
Threads
(C++11)
(C++20)
this_thread namespace
(C++11)
(C++11)
Cooperative cancellation
Mutual exclusion
Generic lock management
lock
(C++11)
(C++11)
(C++11)
(C++11)
Condition variables
(C++11)
Semaphores
Latches and Barriers
(C++20)
(C++20)
Futures
(C++11)
(C++11)
(C++11)
Safe reclamation
Hazard pointers
Atomic types
(C++11)
(C++20)
Initialization of atomic types
(C++11) (deprecated in C++20)
(C++11) (deprecated in C++20)
Memory ordering
(C++11) (deprecated in C++26)
Free functions for atomic operations
Free functions for atomic flags
헤더 파일에 정의됨 <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)
try_lock 호출을 반복하여 뮤텍스 소유권 획득 시도
(함수 템플릿)
데드락 방지 다중 뮤텍스 RAII 래퍼
(클래스 템플릿)