반응형

1. 설명

- 원자적으로 처리할 변수에 대해 정의한다.

- 쓰레드 동작시 공유 변수의 동시성(Concurrency) 문제에 대해 해결해 준다.

 

 

2. 문제 상황

- 아래의 코드를 실행해보면 전역 변수 num을 2개의 쓰레드가 각각 더하거나 뺀다.

- 더하거나 빼는 과정에 문맥교환(Context Switching)이 일어나면 연산이 완료되기 전에 제어권을 빼앗길 수 있다.

- 더하거나 빼는 연산을 원자적으로 처리하기 위해 atomic 변수로 선언이 필요하다.

#include <iostream>
#include <thread>

int num{0};

void ThreadHandler(const bool isAdd)
{
    for (int i=0; i<1000000; i++)
    {
    	if (isAdd) num++;
        else num--;
    }
    
    std::cout << "num=" << num << std::endl;
}

int main()
{
    std::jthread thr1{ThreadHandler, true};
    std::jthread thr2{ThreadHandler, false};
    
    return 0;
}

 

3. 사용법

#include <atomic>

std::atomic< var-type > var;

 

(1) 인자

  1-1) var-type : 변수나 객체의 타입을 지정

 

4. 사용 예제

- 위에서 문제가 됐던 num 변수의 타입을 std::atomic<int>로 변경해 준다.

- 이제 num 변수의 원자성이 보장되기 때문에 마지막 출력값은 항상 0이 된다.

#include <iostream>
#include <thread>
#include <atomic>

std::atomic<int> num{0}; //atomic 변수 선언

void ThreadHandler(const bool isAdd)
{
    for (int i=0; i<1000000; i++)
    {
    	if (isAdd) num.fetch_add(1); //atomic 값을 증가 (num++ 사용가능)
        else num.fetch_sub(1); //atomic 값을 감소 (num-- 사용가능)
    }
    
    std::cout << "num=" << num.load() << std::endl; //atomic 값을 출력
}

int main()
{
    num.store(0); //atomic 변수 초기화
    
    std::jthread thr1{ThreadHandler, true};
    std::jthread thr2{ThreadHandler, false};
    
    return 0;
}

 

 

 

 

반응형

+ Recent posts