方法一

针对一写多读场景,可以使用智能指针代替锁

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <iostream>
#include <vector>
#include <map>
#include <memory>
#include <atomic>
#include <thread>

void LoadMap(std::shared_ptr<std::map<int, int>> map_ptr) {
  std::cout << "LoadMap" << std::endl;
  for (int i = 0; i < 10000; i++) {
    (*map_ptr)[i] = (*map_ptr)[i] + 1;
  }
}

class DoubleBuffer {
  private:  
    std::vector<std::shared_ptr<std::map<int, int>>> buffers_;
    std::atomic_size_t curr_;
  public:
    DoubleBuffer() : curr_(0) {
      buffers_.push_back(std::make_shared<std::map<int, int>>());
      buffers_.push_back(std::make_shared<std::map<int, int>>());
      for (int i = 0; i < 10000; i++) {
        (*buffers_[0])[i] = 0;
        (*buffers_[1])[i] = 0;
      }
    }
    void set() {
      size_t prepare = 1 - curr_.load();
      while(buffers_[prepare].use_count() > 1) {
        continue;
      }
      LoadMap(buffers_[prepare]);
      curr_ = prepare;
    }
    int get(int key) {
      return (*buffers_[curr_.load()])[key];
    }
};

int main() {
  DoubleBuffer db;
  // 定义写线程,每隔1s写一次
  std::thread t1([&db](){
    for(int i = 0; i < 3; i++) {
      db.set();
    }
  });
  // 定义读线程1
  std::thread t2([&db](){
    for(int i = 0; i < 10000; i++) {
      std::cout << db.get(i) << std::endl;
    }
  });
  // 定义读线程2
  std::thread t3([&db](){
    for(int i = 0; i < 10000; i++) {
    std::cout << db.get(i) << std::endl;
    }
  });
  t1.join();
  t2.join();
  t3.join();
  return 0;
}