vector<int> v;
void Push()
{
for(int i = 0 ; i < 10000 ; i++)
{
v.push_back(i);
}
}
int main()
{
std::thread t1(Push);
std::thread t2(Push);
t1.join();
t2.join();
cout << v.size() << endl;
return 0;
}
실행 결과
오류 발생
v.reserve(20000)으로 미리 20000크기의 공간을 할당받으면 오류는 사라지지만, 여전히 원자성은 보장이 되지 않아 결과가 20000이 나오지 않음.vector<int> v;
mutex m;
void Push()
{
for(int i = 0 ; i < 10000 ; i++)
{
m.lock();
v.push_back(i);
m.unlock();
}
}
int main()
{
std::thread t1(Push);
std::thread t2(Push);
t1.join();
t2.join();
cout << v.size() << endl;
return 0;
}
실행 결과
20000
vector<int> v;
mutex m;
template<typename T>
class LockGuard
{
private:
T* _mutex;
public:
LockGuard(T& m)
{
_mutex = &m;
_mutex -> lock();
}
~LockGuard()
{
-mutex -> unlock();
}
}
void Push()
{
for(int i = 0 ; i < 10000 ; i++)
{
LockGuard<std::mutex> lockGuard(m);
v.push_back(i);
if(i == 5000) break;
}
}
int main()
{
std::thread t1(Push);
std::thread t2(Push);
t1.join();
t2.join();
cout << v.size() << endl;
return 0;
}
unlock()을 따로 명시하지 않고도 소멸자를 통해 자동으로 unlock()가능.lock_guard, unique_lock 등의 표준이 있음`
lock_guard는 위의 예시와 동일하게 사용unique_lock은 추가 기능이 더 있음.
unique_lock<mutex> uniqueLock(m, defer_lock)과 같이 defer_lock 옵션을 주면 명시적으로 lock을 하는 타이밍을 정할 수 있음. uniqueLock.lock()과 같이 사용.