2015/06/28 - [Programming/C++11&14] - [C++11] thread 지원 - future를 통한 return값 획득 (2)
이미 대부분의 OS는 동기화를 위한 다양한 장치가 마련되어 있습니다.
thread가 C++11에서 직접 지원하면서 동기화를 위한 std::mutex가 추가되었습니다.
헤더는 <mutex>이며 사용 방법은 다음과 같습니다.
#include <thread> #include <mutex> #include <iostream> std::mutex mtx; void ThreadFunc(int nID, int& nVal) { for (int i = 0 ; i < 5 ; ++i) { mtx.lock(); std::cout << "Value of " << nID << " -> " << nVal << std::endl; ++nVal; mtx.unlock(); } } int main() { int nVal = 0; std::thread th1(ThreadFunc, 0, std::ref(nVal)); std::thread th2(ThreadFunc, 1, std::ref(nVal)); th1.join(); th2.join(); return 0; }
간단하게 객체를 생성하고 lock()으로 권한을 획득하고 공유 데이터에 접근합니다.
그리고 다 사용한 이후에 unlock()을 통해서 해제하면 됩니다.
lock()과 unlock()을 지우면 화면에 정상적으로 출력되지 않는 것을 확인할 수 있습니다.
다만 가끔씩 정상적인 것처럼 출력이 될 수도 있습니다.
그리고 try_lock() 메소드는 권한을 획득하기 위해서 시도합니다.
결과가 바로 리턴되며, 획득에 성공할 경우 true, 실패할 경우 false를 리턴합니다.
바로 획득이 가능할 경우만 작업을 처리하고 싶을 경우에 사용하면 됩니다.
lock()과 try_lock()은 이미 권한을 획득한 thread에서 호출할 경우 미정의 동작이 발생합니다.
lock()을 연달아 사용하고 싶을 때는 std::recursive_mutex를 사용하면 됩니다.
이 경우에는 lock()을 호출한 회수와 동일하게 unlock()을 호출해야 합니다.
#include <thread> #include <mutex> #include <iostream> std::recursive_mutex mtx; void ThreadFunc(int nID, int& nVal) { for (int i = 0; i < 5; ++i) { std::lock_guard<std::recursive_mutex> lg(mtx); std::cout << "Value of " << nID << " -> " << nVal << std::endl; ++nVal; } } int main() { int nVal = 0; std::thread th1(ThreadFunc, 0, std::ref(nVal)); std::thread th2(ThreadFunc, 1, std::ref(nVal)); th1.join(); th2.join(); return 0; }
std::lock_guard는 RAII(Resource Acquisition Is Initialization) 방식으로 동작합니다.
초기화할 때 lock을 획득하고 unlock()을 호출하지 않아도 범위를 벗어나면 자동적으로 해제됩니다.
lock_guard의 기능에 mutex의 메소드까지 호출 가능한 std::unique_lock도 존재합니다.
recursive_mutex를 사용하는 이유는 동일한 mutex를 사용하는 함수가 다른 함수를 호출할 수 있기 때문입니다.
또한 std::timed_mutex와 std::recursive_timed_mutex 등이 존재합니다.
try_lock_until()과 try_lock_for() 등이 추가로 제공됩니다.
이 메소드들은 바로 결과를 주지 않고 지정된 시간만큼 재시도를 하다가 결과를 리턴합니다.
또한 C++17에서는 std::shared_mutex도 추가될 예정입니다.
'Programming > CPP11&14' 카테고리의 다른 글
[C++11] 초기화자 리스트(initializer list)와 std::initializer_list (0) | 2016.12.25 |
---|---|
[C++11] Storage class specifiers에 thread_local 추가 (0) | 2015.07.07 |
[C++11] thread 지원 - future를 통한 return값 획득 (2) (0) | 2015.06.28 |
[C++11] thread 지원 (1) (0) | 2015.06.27 |
[C++11] 새로워진 random number 생성 (0) | 2015.05.22 |