74311
書き込みスレッド同士（あるいは書き込みスレッドと読み込みスレッド間）は排他にしたいですが、読み込みスレッド同士は排他にしたくないとき、どのようにしたらよいでしょうか？

前提：  
スレッドwrite_threadはある値をたまに書き込むことがあります。  
スレッドread_thread0、スレッドread_thread1は値を読み込むことしかしません。

```

    #include <iostream>
    #include <thread>
    
    struct Data{
        float x;
        float y;
        float z;
    };
    
    int main(){
        Data data {0.0f,0.0f,0.0f};
        std::atomic<bool> quit=false;
        std::thread write_thread {
            [&data,&quit]{
                while(!quit){
                    std::this_thread::sleep_for(std::chrono::milliseconds(20));
                    data.x +=1;
                    std::this_thread::sleep_for(std::chrono::milliseconds(20));
                    data.y +=1;
                    std::this_thread::sleep_for(std::chrono::milliseconds(20));
                    data.z +=1;
                }
            }
        };
        
        auto reader = [&data,&quit](unsigned int ms){
                while(!quit){
                    std::this_thread::sleep_for(std::chrono::milliseconds(ms));
                    std::cout << data.x << "," << data.y << "," << data.z << std::endl;
                }
            };
        
        std::thread read_thread0 {reader, 30};
        std::thread read_thread1 {reader, 40};
        std::this_thread::sleep_for(std::chrono::milliseconds(200));
        quit = true;
        write_thread.join();
        read_thread0.join();
        read_thread1.join();
    }
    
```

```

    1,0,0
    1,0,0
    1,1,0
    1,1,1
    2,1,1
    2,2,1
    2,2,1
    3,2,2
    3,2,2
    3,3,2
    3,3,3
    4,3,3
    
    // ゾロ目で出るようにしたいが、read_thread同士が互いにロックを取り合うようなことはしたくない。
    
```

write_thread と read_thread0 はdataに排他的に触る。  
write_thread と read_thread1 はdataに排他的に触る。  
read_thread0 と read_thread1 は互いにロックを取り合わずにdataに触りたい。
CC BY-SA 4.0
2021-02-28T04:21:14.740
74310
2021-02-28T04:30:37.557
2021-02-28T04:30:37.557
37013
37013
question
c++
書き込みスレッドのみと排他にし、読み込みスレッド同士は排他にしないミューテックスはどのように作ったら良いですか？
`std::shared_mutex`を使うことで実現できます。

shared_mutex - cpprefjpから引用

```

    #include <iostream>
    #include <thread>
    #include <shared_mutex>
    #include <chrono>
    
    std::mutex print_mtx;
    void print_value(int x)
    {
      std::lock_guard<std::mutex> lock(print_mtx);
      std::cout << x << std::endl;
    }
    
    class X {
      std::shared_mutex mtx_;
      int count_ = 0;
    public:
      // 書き込み側：カウンタを加算する
      void writer()
      {
        std::lock_guard<std::shared_mutex> lock(mtx_);
        ++count_;
      }
    
      // 読み込み側：カウンタの値を読む
      void reader()
      {
        std::shared_lock<std::shared_mutex> lock(mtx_);
        print_value(count_);
      }
    };
    
    X obj;
    void writer_thread()
    {
      for (int i = 0; i < 3; ++i) {
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
        obj.writer();
      }
    }
    
    void reader_thread()
    {
      for (int i = 0; i < 10; ++i) {
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
        obj.reader();
      }
    }
    
    int main()
    {
      // 書き込みユーザー1人
      // 読み込みユーザー3人
      std::thread writer1(writer_thread);
      std::thread reader1(reader_thread);
      std::thread reader2(reader_thread);
      std::thread reader3(reader_thread);
    
      writer1.join();
      reader1.join();
      reader2.join();
      reader3.join();
    }
    
```
CC BY-SA 4.0
2021-02-28T04:26:45.870
74311
2021-02-28T04:26:45.870
37013
74310
answer