Multiple Reader, Single Writer

  • Financial data feed for infrequently traded stocks

    • Constantly accessed to get the latest price
    • The price rarely changes
  • Audio / video buffers in multimedia players

    • Constantly accessed to get the next frame
    • Occasionally updated with a block of data
  • Shared data

    • Must protect against a data race
  • Concurrent accesses:

    • High probability of a reader and another reader
      • No locking required
    • Low probably of a writer and a reader
      • Locking required
    • Low probability of a writer and another writer
      • Locking required
  • With std::mutex, all threads are synchronized

  • They must execute their critical sections sequentially

    • Even when it is not necessary
  • Lots of concurrency reduces performance


#include <mutex>
#include <thread>
#include <vector>

std::mutex mut;
int x = 0;

void write() {
  std::lock_guard<std::mutex> lck_guard(mut);

  ++x;
}

void read() {
  std::lock_guard<std::mutex> lck_guard(mut);

  using namespace std::literals;
  std::this_thread::sleep_for(100ms);
}

int main() {
  std::vector<std::thread> threads;

  for (int i = 0; i < 20; ++i) {
    threads.push_back(std::thread(read));
  }

  threads.push_back(std::thread(write));
  threads.push_back(std::thread(write));

  for (int i = 0; i < 20; ++i) {
    threads.push_back(std::thread(read));
  }

  for (auto &thr : threads) {
    thr.join();
  }
}

Read-write lock

  • It would be useful to have "selective" locking
    • Lock when there is a thread which is writing
    • Do not lock when there are only reading threads
    • Often called a "read-write lock"