std:: lock_guard
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Member functions | ||||
|
헤더 파일에 정의됨
<mutex>
|
||
|
template
<
class
Mutex
>
class lock_guard ; |
(C++11부터) | |
lock_guard
클래스는 스코프 블록 기간 동안 뮤텍스를 소유하기 위한 편리한
RAII-style
메커니즘을 제공하는 뮤텍스 래퍼입니다.
lock_guard
객체가 생성될 때, 주어진 뮤텍스의 소유권을 획득하려 시도합니다.
lock_guard
객체가 생성된 범위를 벗어나면,
lock_guard
가 소멸되고 뮤텍스가 해제됩니다.
lock_guard
클래스는 복사할 수 없습니다.
목차 |
템플릿 매개변수
| Mutex | - | 잠글 뮤텍스의 유형. 해당 유형은 BasicLockable 요구 사항을 충족해야 함 |
멤버 타입
| 멤버 타입 | 정의 |
mutex_type
|
Mutex |
멤버 함수
lock_guard
를 생성하며, 선택적으로 주어진 뮤텍스를 잠금
(public member function) |
|
lock_guard
객체를 파괴하며, 기반 뮤텍스를 잠금 해제
(public member function) |
|
|
operator=
[deleted]
|
복사 할당 불가
(public member function) |
참고 사항
초보자가 자주 하는 실수 중 하나는
lock_guard
변수에 이름을 지정하는 것을 잊는 것입니다. 예를 들어
std
::
lock_guard
{
mtx
}
와 같이 작성하는 경우입니다. 이는 프라밸류(prvalue) 객체를 생성하여 즉시 파괴하므로, 실제로 스코프 전체에 걸쳐 뮤텍스를 잠그는 록을 생성하지 않게 됩니다.
|
std::scoped_lock
는 데드락 방지 알고리즘을 사용하여 여러 뮤텍스를 잠글 수 있는 기능을 제공하는
|
(C++17부터) |
예제
두 개의 스레드에 의한 volatile 변수의 안전한 증가와 안전하지 않은 증가를 보여줍니다.
#include <iostream> #include <mutex> #include <string_view> #include <syncstream> #include <thread> volatile int g_i = 0; std::mutex g_i_mutex; // protects g_i void safe_increment(int iterations) { const std::lock_guard<std::mutex> lock(g_i_mutex); while (iterations-- > 0) g_i = g_i + 1; std::cout << "thread #" << std::this_thread::get_id() << ", g_i: " << g_i << '\n'; // g_i_mutex is automatically released when lock goes out of scope } void unsafe_increment(int iterations) { while (iterations-- > 0) g_i = g_i + 1; std::osyncstream(std::cout) << "thread #" << std::this_thread::get_id() << ", g_i: " << g_i << '\n'; } int main() { auto test = [](std::string_view fun_name, auto fun) { g_i = 0; std::cout << fun_name << ":\nbefore, g_i: " << g_i << '\n'; { std::jthread t1(fun, 1'000'000); std::jthread t2(fun, 1'000'000); } std::cout << "after, g_i: " << g_i << "\n\n"; }; test("safe_increment", safe_increment); test("unsafe_increment", unsafe_increment); }
가능한 출력:
safe_increment: before, g_i: 0 thread #140121493231360, g_i: 1000000 thread #140121484838656, g_i: 2000000 after, g_i: 2000000 unsafe_increment: before, g_i: 0 thread #140121484838656, g_i: 1028945 thread #140121493231360, g_i: 1034337 after, g_i: 1034337
결함 보고서
다음 동작 변경 결함 보고서들은 이전에 발표된 C++ 표준에 소급 적용되었습니다.
| DR | 적용 대상 | 게시된 동작 | 올바른 동작 |
|---|---|---|---|
| LWG 2981 | C++17 |
lock_guard<Mutex>
에서 중복된 deduction guide가 제공됨
|
제거됨 |
참고 항목
|
(C++11)
|
이동 가능한 뮤텍스 소유권 래퍼를 구현
(클래스 템플릿) |
|
(C++17)
|
데드락 방지 다중 뮤텍스 RAII 래퍼
(클래스 템플릿) |