728x90
반응형
#include <iostream>
using namespace std;
#include <thread>
#include <vector>
#include <Windows.h>
#include <atomic>
#include <mutex>
class Lock
{
public:
void lock()
{
while (_flag)
{
//_flag == true일 때 아래로 못내려 감
}
_flag = true;//_flag == false가 되자마자 true로 바꿔 다른 스레드가 못쓰게 함
}
void unlock()
{
_flag = false;
}
private:
atomic<bool> _flag = false;
};
Lock m;
vector<int> v;
void Push()
{
for (int i = 0; i < 10000; i++)
{
std::lock_guard<Lock> lockGuard(m);
v.push_back(i);
if (i == 5000)
{
break;
}
}
}
int main()
{
v.reserve(100000);
thread t1(Push);
thread t2(Push);
t1.join();
t2.join();
std::cout << v.size() << std::endl;
}
-> 출력 : 9997 (_flag = true를 두 쓰레드가 동시에 실행하여 씹힘)
void lock()
{
while (_flag)
{
//_flag == true일 때 아래로 못내려 감, _flag가 false일 때 탈출함
}
//_flag == false가 되자마자 true로 바꿔 다른 스레드가 못쓰게 함
_flag = true;
}
위처럼 _flag가 false가 될 때 쓰레드 두개가 동시에 _flag를 true로 만드는 문제가 있음
이를 해결하기 위해 CPU 레벨에서 아래 과정을 순차적이 아니라 한번에 처리 함
bool expected = false;
bool desired = true;
if (_flag == expected ( = false))
{
_flag = desired ( = true);
//_flag == false가 되자마자 true로 바꿔 다른 스레드가 못쓰게 함
return true; //성공했는지 실패했는지를 알려 줌
}
else
{
expected = _flag ( = false);
return false;
}
compare_exchange_strong함수의 첫 번째 파라미터는 레퍼런스로 받기 때문에 값이 계속해서 변하게 된다. 그렇기 때문에 초기 값으로 계속해서 초기화를 해줘야 정상적으로 작동한다. 이해하기 어렵다면 맨 아래의 compare_exchange_strong의 의사코드를 먼저 보는 것을 추천한다.
https://m.blog.naver.com/han931120/223565699718
이를 compare_exchange_strong로 표현하면
void lock()
{
bool expected = false;
bool desired = true;
_flag.compare_exchange_strong(expected, desired);
while (_flag.compare_exchange_strong(OUT expected, desired) == false)
{
expected = false;
}
}
728x90
반응형
'코드 > C++' 카테고리의 다른 글
deadlock (0) | 2024.11.26 |
---|---|
Lock (0) | 2024.11.12 |
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 |
댓글