Lazy Initialization

  • Common pattern in functional programming
  • A variable is only initialized when it is first used
  • This is useful when the variable is expensive to construct
    • e.g. it sets up a network connection
  • Can be used in multi-threaded code
    • But we need to avoid data races

#include <mutex>

class Test {
public:
  void func() { /*...*/ }
};

Test *ptest = nullptr; // Variable to be lazily initialized
std::mutex mut;

void process() {
  std::unique_lock<std::mutex> uniq_lck(mut);

  if (!ptest)
    ptest = new Test;
  uniq_lck.unlock();
  ptest->func();
}

  • Every thread that calls process() locks the mutex
    • Locking the mutex blocks every other thread that calls process()
  • The lock is only needed while ptest is being initialized
    • Once ptest has been initialized, locking the mutex is unnecessary
    • Causes a loss of performance