반응형
원자성 (Atomicity)
- 연산이 도중에 중단되지 않고 전체가 완료되거나 전혀 수행되지 않는 것
- 원자성이 지켜져야 멀티스레드 환경에서 데이터의 일관성을 유지하고 동시성 문제를 해결할 수 있다.
다음 코드를 실행해 보자.
#include <iostream>
#include <thread>
using namespace std;
int counter;
void incrementCounter()
{
for (int i = 0; i < 1000000; i++) counter++;
}
int main()
{
thread t1(incrementCounter);
thread t2(incrementCounter);
t1.join();
t2.join();
cout << "Counter : " << counter << endl;
return 0;
}
두 개의 스레드가 counter 변수를 동시에 증가시키고 있다.
따라서 원하는 값인 2000000가 아니라 1000000 ~ 2000000 사이의 값이 나오게 된다.
Atomic (원자 연산)
C++의 std::atomic은 원자 연산을 통해 데이터의 일관성을 보장한다.
특정 연산이 다른 스레드에 의해 중단되지 않으며 전체적으로 완료되도록 한다.
다음과 같이 counter 변수를 atomic으로 선언하면 된다.
#include <atomic>
std::atomic<int> counter(0);
아래와 같이 수정하면 정상적으로 Counter : 2000000을 얻는다.
#include <iostream>
#include <atomic>
#include <thread>
using namespace std;
atomic<int> counter(0);
void incrementCounter()
{
for (int i = 0; i < 1000000; i++) counter++;
}
int main()
{
thread t1(incrementCounter);
thread t2(incrementCounter);
t1.join();
t2.join();
cout << "Counter : " << counter << endl;
return 0;
}
Mutex (상호배제)
C++의 std::mutex는 여러 스레드가 동시에 공유 데이터에 접근하는 것을 막는다.
Critical Section에 진입할 때 해당 스레드는 뮤텍스를 잠그거나 해제해서 데이터를 보호한다.
#include <iostream>
#include <mutex>
#include <thread>
using namespace std;
mutex counterMutex;
int counter = 0;
void incrementCounter()
{
for (int i = 0; i < 1000000; i++)
{
lock_guard<mutex> lock(counterMutex);
counter++;
}
}
int main()
{
thread t1(incrementCounter);
thread t2(incrementCounter);
t1.join();
t2.join();
cout << "Counter : " << counter << endl;
return 0;
}
반응형
'개발 > C, C++' 카테고리의 다른 글
C++ - CRTP로 인터페이스 만들기 (Interface with Curiously Recurring Template Pattern) (0) | 2024.03.06 |
---|---|
C++ - friend로 private 멤버 출력하기 (Printing private members using friend) (0) | 2024.02.13 |
C++ - call_once로 함수를 한 번만 호출하기 (0) | 2024.01.24 |
C++ - 정수를 IP로 변환하기 (IP Converter for IPv4, IPv6, Integer, in_addr, in6_addr) (1) | 2023.11.28 |
C++ - 연산자 오버로딩을 이용하여 구조체 출력하기 (cout with overloading) (0) | 2023.11.22 |
댓글