std::mutex (Mutual Exclusion)
여러 쓰레드가 동시에 공유 자원에 접근할 때 발생 할 수 있는 문제를 방지하는 역할을 해준다.
mutex 사용법
// Mutual Exclusive (상호배타적)
mutex m;
void Push()
{
for (int32 i = 0; i < 10000; ++i)
{
// 잠금 장치
m.lock();
vec.push_back(i);
// 잠금 해제
m.unlock();
}
}
int main()
{
std::thread t1(Push);
std::thread t2(Push);
if (t1.joinable() && t2.joinable())
{
t1.join();
t2.join();
}
cout << vec.size() << endl;
}
t1, t2의 두개의 쓰레드가 Push()를 실행할 때 mutex를 통해 하나의 쓰레드만 접근할 수 있도록 lock()을 통해 접근을 막고 연산이 끝나면 unlock()으로 잠금 장치를 해제한다.
예외 상황
// Mutual Exclusive (상호배타적)
mutex m;
void Push()
{
for (int32 i = 0; i < 10000; ++i)
{
// 잠금 장치
m.lock();
vec.push_back(i);
// 조건으로 인해 탈출할 경우 문제가 발생
if (i == 5000)
{
break;
}
// 잠금 해제
m.unlock();
}
}
int main()
{
std::thread t1(Push);
std::thread t2(Push);
if (t1.joinable() && t2.joinable())
{
t1.join();
t2.join();
}
cout << vec.size() << endl;
}
조건으로 인해 break가 걸리게 되면 mutex로 잠금을 했지만 해제를 하지 않아 문제가 발생한다.
해결 방법
RAII 패턴 사용
// Mutual Exclusive (상호배타적)
mutex m;
template<typename T>
class LockGuard
{
public:
// 생성자에서 lock을 걸고
LockGuard(T& m)
{
_mutex = &m;
_mutex->lock();
}
// 소멸자에서 unlock으로 해제 한다.
~LockGuard()
{
_mutex->unlock();
}
private:
T* _mutex;
};
void Push()
{
for (int32 i = 0; i < 10000; ++i)
{
// 잠금 후 범위 벗어나면 자동 해제 (RAII 패턴)
LockGuard<mutex> lockGuard(m);
vec.push_back(i);
}
}
int main()
{
std::thread t1(Push);
std::thread t2(Push);
if (t1.joinable() && t2.joinable())
{
t1.join();
t2.join();
}
cout << vec.size() << endl;
}
c++ 표준이 지원하는 방법들
lock_guard, unique_lock
void Push()
{
for (int32 i = 0; i < 10000; ++i)
{
// 잠금 후 범위 벗어나면 자동 해제 (RAII 패턴)
lock_guard<mutex> lockGuard(m);
// 기본적으로 lock_guard와 같이 RAII 패턴 적용
// lock_guard 기능 + Lock 시점을 정할 수 있다.
unique_lock<mutex> uniqueLock(m, defer_lock);
uniqueLock.lock();
vec.push_back(i);
}
}
timed_lock
mutex m;
timed_mutex tMtx;
// 특정 시간동안 잠금을 시도한다.
if (tMtx.try_lock_for(chrono::seconds(5)))
{
// 잠금이 성공 되면 실행될 코드
}
// 특정 시간동안 잠금을 시도한다.
unique_lock<mutex> timeLock(m, chrono::seconds(5));
'C, C++' 카테고리의 다른 글
| [[noreturn]] (0) | 2025.01.27 |
|---|---|
| [[deprecated]] (0) | 2025.01.26 |
| <atomic> (0) | 2024.02.21 |
| <thread> (0) | 2024.02.20 |
| weak_ptr (0) | 2023.07.17 |