728x90
반응형
#include <iostream>
using namespace std;
#include <thread>
#include <vector>
#include <Windows.h>
#include <atomic>
#include <mutex>
mutex m;
vector<int> v;
void Push()
{
for (int i = 0; i < 10000; i++)
{
v.push_back(i);
}
}
int main()
{
thread t1(Push);
thread t2(Push);
t1.join();
t2.join();
cout << v.size() << endl;
}
-> crash
-> heap 영역에 동적 할당 받은 공간이 꽉 찰 경우 공간을 재할당 받아 데이터를 이동시키는 vector의 특징으로 인해
t1이 v[0]의 주소를 0x0001에서 0x0009로 재할당 받아 이동해 갔는데도 불구하고 t2는 여전히 0x0001을 가리키고 있고 여기에 값을 쓰려다 crash가 발생
#include <iostream>
using namespace std;
#include <thread>
#include <vector>
#include <Windows.h>
#include <atomic>
#include <mutex>
mutex m;
vector<int> v;
void Push()
{
for (int i = 0; i < 10000; i++)
{
v.push_back(i);
}
}
int main()
{
v.reserve(20000);
thread t1(Push);
thread t2(Push);
t1.join();
t2.join();
cout << v.size() << endl;
}
-> crash는 피했으나 출력 : 19999
-> [0][1][2][ ]
-> v[4]에 t1과 t2가 동시에 push_back(3)을 할 경우 발생
#include <iostream>
using namespace std;
#include <thread>
#include <vector>
#include <Windows.h>
#include <atomic>
#include <mutex>
mutex m;
vector<int> v;
void Push()
{
for (int i = 0; i < 10000; i++)
{
m.lock();
v.push_back(i);
m.unlock();
}
}
int main()
{
v.reserve(20000);
thread t1(Push);
thread t2(Push);
t1.join();
t2.join();
cout << v.size() << endl;
}
-> 출력 : 20000, m.lock(), m.unlock() 사용
-> t1이 문을 잠그고 작업하는 동안 t2는 대기 함
#include <iostream>
using namespace std;
#include <thread>
#include <vector>
#include <Windows.h>
#include <atomic>
#include <mutex>
mutex m;
vector<int> v;
void Push()
{
for (int i = 0; i < 10000; i++)
{
m.lock();
v.push_back(i);
if (i == 5000)
{
//m.unlick();
break;
}
m.unlock();
}
}
int main()
{
v.reserve(20000);
thread t1(Push);
thread t2(Push);
t1.join();
t2.join();
cout << v.size() << endl;
}
-> 반복문을 탈출할 때 m.unlock()을 생략하면 Push함수에서 m잠금을 해제하지 못함
#include <iostream>
using namespace std;
#include <thread>
#include <vector>
#include <Windows.h>
#include <atomic>
#include <mutex>
mutex m;
vector<int> v;
template<typename T>
class LockGuard
{
public:
LockGuard(T& m) : _mutex(m)
{
_mutex.lock();
}
~LockGuard()
{
_mutex.unlock();
}
private:
T& _mutex;
};
void Push()
{
for (int i = 0; i < 10000; i++)
{
LockGuard<mutex> lockGuard(m);
v.push_back(i);
if (i == 5000)
{
break;
}
}
}
int main()
{
v.reserve(20000);
thread t1(Push);
thread t2(Push);
t1.join();
t2.join();
cout << v.size() << endl;
}
-> 생성자 (LockGuard<mutex> lockGuard(m))에서 잠그고 for를 빠져나갈 때 소멸자에서 푼다.
(변형)
#include <iostream>
using namespace std;
#include <thread>
#include <vector>
#include <Windows.h>
#include <atomic>
#include <mutex>
mutex m;
vector<int> v;
template<typename T>
class LockGuard
{
public:
LockGuard(T& m) : _mutex(m)
{
_mutex.lock();
}
~LockGuard()
{
_mutex.unlock();
}
private:
T& _mutex;
};
void Push()
{
cout << "in" << endl;
for (int i = 0; i < 10000; i++)
{
LockGuard<mutex> lockGuard(m);
v.push_back(i);
if (i == 9999)
{
cout << "out" << endl;
break;
}
}
}
int main()
{
v.reserve(20000);
thread t1(Push);
thread t2(Push);
t1.join();
t2.join();
cout << v.size() << endl;
}
-> t1, t2 동시에 진입, 순차적으로 나감
* 표준 라이브러리에 이미 생성되어 있음, std::lock_guard<mutex> lockGuard(m);
(예제)
#include <iostream>
using namespace std;
#include <thread>
#include <vector>
#include <Windows.h>
#include <atomic>
#include <mutex>
mutex m;
vector<int> v;
template<typename T>
class LockGuard
{
public:
LockGuard(T& m) : _mutex(m)
{
cout << "① 생성 : " << this_thread::get_id() << endl;
_mutex.lock();
}
~LockGuard()
{
cout << "③ 파괴 : " << this_thread::get_id() << endl;
_mutex.unlock();
}
private:
T& _mutex;
};
void Push()
{
for (int i = 0; i < 10; i++)
{
LockGuard<mutex> lockGuard(m);
cout << "② 실행 : " << this_thread::get_id() << endl;
v.push_back(i);
if (i == 9)
{
cout << "④ 퇴장" << endl;
break;
}
}
}
int main()
{
v.reserve(20000);
thread t1(Push);
thread t2(Push);
t1.join();
t2.join();
cout << v.size() << endl;
}
->
1. cout << ⓐ << ⓑ << endl에서 ⓐ와 ⓑ가 분할되어 실행 (한줄의 코드를 2회에 나눠 작업함)
2. t1과 t2 스레드가 개별적으로 생성 -> 실행 -> 파괴의 순서로 실행됨
728x90
반응형
'코드 > C++' 카테고리의 다른 글
deadlock (0) | 2024.11.26 |
---|---|
spin lock (0) | 2024.11.19 |
PE File Format, notepad (0) | 2024.06.10 |
release 배포 시 dll 오류 날 때 (2) | 2023.11.21 |
std::to_wstring(int), _tow_s(int, wchar_t, 2 or 10); (0) | 2023.11.16 |
댓글