C++/Library 2021. 3. 30. 00:03

mutex

  • <mutex> 라이브러리

  • Mutual Exclusion의 약자이다.


예제

  • mutex를 적용하지 않은 예제

    • 출력이 섞여서 나오는 것을 볼 수 있다.
    #include <iostream>
    #include <thread>
    #include <chrono>
    
    int         main()
    {
        using namespace std;
    
        const int num_logical_processors = std::thread::hardware_concurrency();
    
        cout << "Number of processors : " << num_logical_processors << endl;
        cout << "ID of this thread : " << std::this_thread::get_id() << endl;
    
        auto work_func = [](const string& name)
        {
            for (int i = 0; i < 5; ++i)
            {
                std::this_thread::sleep_for(std::chrono::milliseconds(100));
                cout << name << ' ' << std::this_thread::get_id() << " is working " << i << endl;
            }
        };
    
        std::thread t1 = std::thread(work_func, "Jack Jack");
        std::thread t2 = std::thread(work_func, "Dash");
    
        t1.join();
        t2.join();
    }
    
    /* stdout stderr
    Number of processors : 12
    ID of this thread : 16040
    Jack Jack 5336 is working 0
    Dash 8368 is working 0
    Jack Jack 5336 is working 1Dash 8368 is working 1
    
    Dash 8368 is working 2
    Jack Jack 5336 is working 2
    Dash 8368 is working 3
    Jack Jack 5336 is working 3
    Jack Jack 5336 is working 4
    Dash 8368 is working 4
    */

  • mutex를 사용한 예제

    #include <iostream>
    #include <thread>
    #include <chrono>
    #include <mutex>
    
    int         main()
    {
        using namespace std;
    
        mutex mtx;
    
        const int num_logical_processors = std::thread::hardware_concurrency();
    
        cout << "Number of processors : " << num_logical_processors << endl;
        cout << "ID of this thread : " << std::this_thread::get_id() << endl;
    
        auto work_func = [&](const string& name)
        {
            for (int i = 0; i < 5; ++i)
            {
                std::this_thread::sleep_for(std::chrono::milliseconds(100));
    
                mtx.lock();
                cout << name << ' ' << std::this_thread::get_id() << " is working " << i << endl;
                mtx.unlock();
            }
        };
    
        std::thread t1 = std::thread(work_func, "Jack Jack");
        std::thread t2 = std::thread(work_func, "Dash");
    
        t1.join();
        t2.join();
    }
    
    /* stdout stderr
    Number of processors : 12
    ID of this thread : 1588
    Jack Jack 17596 is working 0
    Dash 14068 is working 0
    Jack Jack 17596 is working 1
    Dash 14068 is working 1
    Dash 14068 is working 2
    Jack Jack 17596 is working 2
    Jack Jack 17596 is working 3
    Dash 14068 is working 3
    Dash 14068 is working 4
    Jack Jack 17596 is working 4
    */
    • 만약 mutex.unlock()을 하지 않으면 다른 쓰레드에서 해당 자원을 사용할 수 없다.

C++11

lock_guard

  • mutex.lock(), mutex.unlock()을 사용하지 않고, 정의하면 락이 걸리고 영역을 벗어나면 언락을 해주는 클래스이다.

  • C++17부터는 템플릿타입 자리에 아무것도 안넣어도 된다. (lock_guard lock(mtx) 이런 식으로)

    #include <iostream>
    #include <thread>
    #include <chrono>
    #include <mutex>
    
    int         main()
    {
        using namespace std;
    
        int shared_memory(0);
        mutex mtx;
    
        auto count_func = [&]() {
            for (int i = 0; i < 1000; ++i)
            {
                this_thread::sleep_for(chrono::milliseconds(1));
    
                lock_guard<mutex> lock(mtx);
    
                shared_memory++;
            }
        };
    
        thread t1 = thread(count_func);
        thread t2 = thread(count_func);
    
        t1.join();
        t2.join();
    
        cout << "Value is " << shared_memory << endl;
    }
    
    /* stdout stderr
    Value is 2000
    */

C++17

scoped_lock

  • 뮤텍스 락을 자주 걸면 오버헤드가 커지므로 성능 저하가 발생한다.

  • lock_guard에서 여러 mutex를 한번에 lock할 수 있는 기능을 추가한 클래스라고 한다. 즉 상위 호환이다.

    #include <iostream>
    #include <thread>
    #include <chrono>
    #include <mutex>
    
    int         main()
    {
        using namespace std;
    
        int shared_memory(0);
        mutex mtx;
    
        auto count_func = [&]() {
            for (int i = 0; i < 1000; ++i)
            {
                this_thread::sleep_for(chrono::milliseconds(1));
    
                scoped_lock<mutex> lock(mtx);
    
                shared_memory++;
            }
        };
    
        thread t1 = thread(count_func);
        thread t2 = thread(count_func);
    
        t1.join();
        t2.join();
    
        cout << "Value is " << shared_memory << endl;
    }
    
    /* stdout stderr
    Value is 2000
    */

'C++ > Library' 카테고리의 다른 글

C++ 멀티쓰레딩 (Multithreading)  (0) 2021.03.30
C++ atomic  (0) 2021.03.30
C++ 파일 임의 위치 접근  (0) 2021.03.29
C++ fstream  (0) 2021.03.29
C++ 정규 표현식 (Regular Expressions)  (0) 2021.03.29