Mutex
- lock 함수로 임계 구역 (critical section) 진입 전 자신만 임계 구역에 들어가겠다고 함
- unlock 함수로 임계 구역 탈출 후 다른 사람들도 임계 구역에 진입 가능하도록 만듬
Condition Variable
- wait 시 인자로 받은 mutex를 unlock 함
- notify_one 함수로 잠자는 것들 중 하나를 깨울 수 있음
- notify_all 함수로 잠자는 것들 모두를 깨울 수 있음
Reader-Writer 문제에서 mutex와 condition variable을 사용한다면
<iostream>
<mutex>
<condition_variable>
std::mutex mtx;
std::condition_variable cv;
int num_writers_waiting;
bool writer_active;
int num_readers_active;
int readStart() {
std::lock_guard<std::mutex> lock(mtx);
num_readers_active++;
while (num_writers_waiting > 0 || writer_active) {
cv.wait();
}
} // as goes out of scope, mtx unlocked (lock_guard 기능)
int readEnd() {
std::lock_guard<std::mutex> lock(mtx);
num_readers_active--;
if (num_readers_active == 0) cv.notify_all();
} // as goes out of scope, mtx unlocked (lock_guard 기능)
int writeStart() {
std::lock_guard<std::mutex> lock(mtx);
num_writers_waiting++;
while (num_readers_active > 0 || writer_active) {
cv.wait();
}
num_writers_waiting--;
writer_active = true;
} // as goes out of scope, mtx unlocked (lock_guard 기능)
int writeEnd() {
std::lock_guard<std::mutex> lock(mtx);
while (num_readers_active > 0 || writer_active) {
cv.wait();
}
writer_active = false;
cv.notify_all();
} // as goes out of scope, mtx unlocked (lock_guard 기능)
코드 분석
- std::lock_guard를 사용하면 C++ 의 RAII 원칙을 따르면서 일일히 여러 경우에 관해 unlock 함수를 써줄 필요가 없다
- RAII (Resource Acquisition Is Initialization): 선언 시에 메모리가 할당되고 scope에 벗어나 정리될 때 자동으로 메모리도 해제 됨
- 위 예제는 writer를 우선으로 해서 1명이라도 write를 기다리고 있으면 더 이상 reader를 늘리지 않습니다.
- condition variable은 위 예제 처럼 mutex와 condition을 나타낼 변수와 함께 사용됩니다.
- 예) writer_active 가 true 라면 (누군가 쓰고 있다면) condition variable의 wait을 불러 mutex lock을 해제하고 다른 이들이 notify를 호출해 깨워주는 것을 기다립니다.
- conditon variable과 mutex를 같이 사용하는 이유는 condition을 나타낼 변수 또한 수정하는데 있어서 경쟁 상태가 발생 할 수 있기 때문에 condition 변수 수정 전 lock을 잡고 condition 변수 수정 또한 atomic 하게 이루어지게 하기 위함입니다.
- notify를 통해 깨워났을 때 다시 lock을 갖게 됩니다.
'개발 관련 기타 > C++' 카테고리의 다른 글
C++) static 멤버 변수 life cycle (0) | 2020.09.28 |
---|---|
C++) [스마트 포인터] weak_pointer, unique_pointer, shared_pointer (0) | 2020.09.28 |
C++) std::bind 와 std::placeholders (std::placeholders::_1, std::placeholders::_2, ...) (0) | 2020.06.24 |
C++) RAII 디자인 패턴 (0) | 2020.05.28 |
(C언어) epoll 정의 (0) | 2019.12.02 |