ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • shared_mutex, 그리고 upgrade_lock.
    프로그래밍/c++ 2015. 12. 28. 09:25
    반응형

    shared_mutex?

     

    읽기/쓰기 락을 지원하는 뮤텍스.

    데이터를 수정하지 않고 읽기만 한다면, n개의 스레드에서 접근하더라도 아무런 문제가 없다.

    하지만 쓰기, 수정이 일어나야 한다면? 읽기도 막아야한다.

    따라서, 읽기만 하는 상황에선 읽기 락을 걸어 n개의 스레드에서 접근이 가능하도록 하고,

    쓰기를 해야 상황에선 1개의 스레드에서만 접근 가능하도록 하는 락을 지원하는 뮤텍스이다

    이 락 readers writer lock이라고도 불림.


    지금(2015/12/xx) 기준으론 boost 라이브러리에만 존재하지만, 

    c++17에는 공식적으로 편입될 예정(http://en.cppreference.com/w/cpp/thread/shared_mutex)


    헤더는 #include <boost/shared_mutex.hpp>

    그리고 boost::shared_mutex를 선언한다.

     

    읽기 (n개의 스레드가 접근할 있는 )

     

    boost::shared_lock<boost::shared_mutex> rlock{ mutex_ };

    *shared_lock 쓴다.


     

    쓰기 (1개의 스레드만 접근할 있는 )

     

    boost::unique_lock<boost::shared_mutex> wlock{ mutex_ };

    *unique_lock 쓴다.

     


    읽기 락과 쓰기 락을 전환하고 싶을 .

     

    기본적으로 upgrade_lock을 선언. upgrade_lock만 선언된 상황에선 읽기로 락을 건다.

    그리고 쓰기 락으로 전환되어야 할 부분에서 boost::upgrade_to_unique_lock을 사용해 읽기 락 => 쓰기 락으로 변경


    boost::upgrade_lock<boost::shared_mutex> rlock{ mutex_ }; // 선언만으론 읽기 락이


    // ... do something


    boost::upgrade_lock<boost::shared_mutex> wlock{ rlock }; // 쓰기락으로 업그레이드!


    // 쓰기 락으로 전환할 상황이 생겼다면..!

    boost::upgrade_to_unique_lock<boost::shared_mutex> wlock{ rlock }; // 읽기 락을 쓰기 락으로 바꿈!


    코드에 적용된 예를 보자.


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
     
      // 읽기 락을 얻습니다.
      boost::upgrade_lock<boost::shared_mutex> lock{ mutex_ };
     
      // 검색자를 획득합니다.
      auto& finder = user_cache.get<user_container::idx_type::id>();
     
      auto it = finder.find(id.data());
      if (it == finder.end())
      {// 캐시에 정보가 없을 때.
        
        // db로부터 데이터를 획득을 시도합니다.
        auto data = load_user_account_from_db(id);
     
        if (data)
        {// 데이터를 획득했을 때
          auto userdata = *data;
     
          account acc;
          acc.id = userdata.id.data();
          acc.nickname = userdata.nickname.data();
          acc.usercode = userdata.usercode;
          acc.pw = userdata.pw.data();
          acc.num_lose = userdata.num_lose;
          acc.num_win = userdata.num_win;
     
          // 읽기 락을 쓰기 락으로 전환합니다.
          boost::upgrade_to_unique_lock<boost::shared_mutex> wlock{ lock };
     
          // 캐시에 삽입합니다.
          user_cache.insert(acc);
          handler(data);
        }
    cs


     

    여튼 핵심은


    upgrade_lock => 읽기/쓰기 락을 전환할 있는 락인데 기본적으론 읽기 락이다. 

    upgrade_to_unique_lock => 업그레이드 (읽기 락) 쓰기 락으로 바꿈


     

    참고


    http://stackoverflow.com/questions/7378266/upgrading-boostshared-lock-to-exclusive-lock

    http://boost.2283326.n4.nabble.com/boost-shared-locks-and-boost-upgrade-locks-td4171304.html

    http://blog.naver.com/wnsdud98/130132612632

    반응형
Designed by Tistory.