(C++ : Concurrency) 13. atomic - 2

Posted by : at

Category : Cpp


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

std::mutex m;

bool use_flag = false;

void work()
{
    //m.lock();
    // mutex를 쓰지말고 bool을 이용할순 없을까? -> busy waiting(혹은 spin-lock)
        // busy waiting
            // sleep을 하지않고 루프를 돌면서 대기
            // CPU자원을 계속 낭비하기에 일반적으로 좋지는 않음
            // 단, 공유자원을 참조하는시간이 지극히 작을경우 오히려 좋음.(lock보다 빠름)

    while(use_flag);
    usg_flag = true;    // 사용중
    std::cout << "start. using shared resource" << std::endl;
    std::cout << "end. using shared resource" << std::endl;
    usg_flag = false;   // 이게 멀티스레드에 세이프할까? -> 느낌상 세이프지 않음
    //m.unlock();
}

int main()
{
    std::jthread t1(work), t2(work);
}

해결해보자

  • std::atomic_flag를 이용할 예정이고
    • 동작은 std::atomic<bool>과 거의 유사한데
    • lock-free(CPU 명령에서 동기화 지원)을 지원하고
    • 최소의 멤버함수를 제공하기에 실수가 적다(store, load없음)
#include <iostream>
#include <atomic>
#include <thread>

// std::atomic_flag flag = ATOMIC_FLAG_INIT;
// C++20이후에는 초기화를 굳이 하지않아도 됨
std::atomic_flag flag;  // false로 초기화 된다.

void work()
{
    while(flag.test_and_set());
    usg_flag = true;
    std::cout << "start. using shared resource" << std::endl;
    std::cout << "end. using shared resource" << std::endl;
    flag.clear();   // flag = false
}

int main()
{
    std::jthread t1(work), t2(work);
}

Example

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

class spinlock
{
    std::atomic_flag flag;
public:
    void lock() {while(flag.test_and_set());}
    void unlock() {flag.clear();}
};
spinlock spin;

void work()
{
    spin.lock();
    std::cout << "start. using shared resource" << std::endl;
    std::cout << "end. using shared resource" << std::endl;
    spin.unlock();
}

atomic_ref(C++20)

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

struct Machine
{
    int data{0};
    int count{0};
};
Machine m;

void foo()
{
    // 레퍼런스처럼 동작하지만 아토믹
    std::atomic_ref<int> cnt{m.count};
    for(int i = 0; i < 1000000; i++)
    {
        //++(m.count);
        ++cnt;
    }
}

int main()
{
    {
        std::jthread t1(foo), t2(foo), t3(foo);
    }
    std::cout << m.count << std::endl;
}

About Taehyung Kim

안녕하세요? 8년차 현업 C++ 개발자 김태형이라고 합니다. 😁 C/C++을 사랑하며 다양한 사람과의 협업을 즐깁니다. ☕ 꾸준한 자기개발을 미덕이라 생각하며 노력중이며, 제가 얻은 지식을 홈페이지에 정리 중입니다. 좀 더 상세한 제 이력서 혹은 Private 프로젝트 접근 권한을 원하신다면 메일주세요. 😎

Star
Useful Links