std:: scoped_lock
|
헤더 파일에 정의됨
<mutex>
|
||
|
template
<
class
...
MutexTypes
>
class scoped_lock ; |
(C++17부터) | |
scoped_lock
클래스는 스코프 블록 기간 동안 0개 이상의 뮤텍스를 소유하기 위한 편리한
RAII-style
메커니즘을 제공하는 뮤텍스 래퍼입니다.
scoped_lock
객체가 생성될 때, 주어진 뮤텍스들의 소유권을 획득하려 시도합니다.
scoped_lock
객체가 생성된 범위를 벗어나면,
scoped_lock
은 소멸되고 뮤텍스들이 해제됩니다. 여러 개의 뮤텍스가 주어졌을 경우,
std::lock
에서처럼 데드락 방지 알고리즘이 사용됩니다.
scoped_lock
클래스는 복사할 수 없습니다.
목차 |
템플릿 매개변수
| MutexTypes | - | 잠글 뮤텍스의 타입들. Lockable 요구사항을 충족해야 하며, 단 sizeof... ( MutexTypes ) == 1 인 경우에는 유일한 타입이 BasicLockable 를 충족해야 함 |
멤버 타입
| 멤버 타입 | 정의 |
mutex_type
(조건부 존재) |
만약
sizeof...
(
MutexTypes
)
==
1
이면, 멤버 타입
|
멤버 함수
scoped_lock
을 생성하며, 선택적으로 주어진 뮤텍스들을 잠금
(public member function) |
|
scoped_lock
객체를 파괴하며, 기반 뮤텍스들의 잠금을 해제
(public member function) |
|
|
operator=
[deleted]
|
복사 할당 불가
(public member function) |
참고 사항
초보자가 자범하는 흔한 실수 중 하나는
scoped_lock
변수에 이름을 지정하는 것을 "잊는" 것입니다. 예를 들어
std
::
scoped_lock
(
mtx
)
;
(이는 기본 생성되어
mtx
라는 이름의
scoped_lock
변수를 생성함) 또는
std
::
scoped_lock
{
mtx
}
;
(이는 즉시 소멸되는 prvalue 객체를 생성함)와 같이 작성하여, 실제로는 해당 범위 동안 뮤텍스를 보유하는 잠금을 생성하지 않게 됩니다.
| 기능 테스트 매크로 | 값 | 표준 | 기능 |
|---|---|---|---|
__cpp_lib_scoped_lock
|
201703L
|
(C++17) |
std::scoped_lock
|
예제
다음 예제는 데드락 없이 뮤텍스 쌍을 잠그기 위해
std::scoped_lock
을 사용하며 RAII 스타일입니다.
#include <chrono>
#include <functional>
#include <iostream>
#include <mutex>
#include <string>
#include <syncstream>
#include <thread>
#include <vector>
using namespace std::chrono_literals;
struct Employee
{
std::vector<std::string> lunch_partners;
std::string id;
std::mutex m;
Employee(std::string id) : id(id) {}
std::string partners() const
{
std::string ret = "직원 " + id + " has lunch partners: ";
for (int count{}; const auto& partner : lunch_partners)
ret += (count++ ? ", " : "") + partner;
return ret;
}
};
void send_mail(Employee&, Employee&)
{
// 시간이 많이 소요되는 메시징 작업 시뮬레이션
std::this_thread::sleep_for(1s);
}
void assign_lunch_partner(Employee& e1, Employee& e2)
{
std::osyncstream synced_out(std::cout);
synced_out << e1.id << " 및 " << e2.id << "이 잠금을 기다리는 중" << std::endl;
{
// 두 개의 락을 획득할 때 데드락 걱정 없이 std::scoped_lock을 사용하세요
// assign_lunch_partner에 대한 다른 호출들이 데드락을 발생시키고 있습니다
// 또한 RAII 스타일 메커니즘을 편리하게 제공합니다
std::scoped_lock lock(e1.m, e2.m);
// 동등한 코드 1 (std::lock과 std::lock_guard 사용)
// 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);
// 동등한 코드 2 (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);
synced_out << 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
**변경사항 없음 - 번역 불가 항목**
- HTML 태그와 속성은 번역하지 않음
- ``, `` 태그 내부 텍스트는 C++ 전용 용어로 번역 불가
- `std::ref`는 C++ 표준 라이브러리 함수명으로 번역하지 않음(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
**변경사항 없음 - 번역 불가 항목**
- HTML 태그와 속성은 번역하지 않음
- ``, ``, `
(bob));
for (auto& thread : threads)
thread.join();
std::osyncstream
(번역 결과: HTML 태그와 속성은 그대로 유지되었으며, C++ 관련 용어인 `std::osyncstream`은 번역되지 않았습니다)(std::cout) << alice.partners() << '\n'
<< bob.partners() << '\n'
<< christina.partners() << '\n'
<< dave.partners() << '\n';
}
가능한 출력:
Alice와 Bob이 락을 기다리고 있습니다 Alice와 Bob이 락을 획득했습니다 Christina와 Bob이 락을 기다리고 있습니다 Christina와 Alice가 락을 기다리고 있습니다 Dave와 Bob이 락을 기다리고 있습니다 Dave와 Bob이 락을 획득했습니다 Christina와 Alice가 락을 획득했습니다 Christina와 Bob이 락을 획득했습니다 직원 Alice의 점심 식사 파트너: Bob, Christina 직원 Bob의 점심 식사 파트너: Alice, Dave, Christina 직원 Christina의 점심 식사 파트너: Alice, Bob 직원 Dave의 점심 식사 파트너: Bob
결함 보고서
다음의 동작 변경 결함 보고서들은 이전에 발표된 C++ 표준에 소급 적용되었습니다.
| DR | 적용 대상 | 게시된 동작 | 올바른 동작 |
|---|---|---|---|
| LWG 2981 | C++17 |
scoped_lock<MutexTypes...>
에서 중복된 deduction guide가 제공됨
|
제거됨 |
참고 항목
|
(C++11)
|
이동 가능한 뮤텍스 소유권 래퍼를 구현함
(클래스 템플릿) |
|
(C++11)
|
엄격한 범위 기반 뮤텍스 소유권 래퍼를 구현함
(클래스 템플릿) |