Skip to content

Safe access to shared data


Some compiler optimizations may cause unexpected behaviour when running multiple threads. For more details see Understanding the problem of synchronization.

When multiple threads are working on the same data there is the danger that one thread changes the data while another thread tries to read and possibly also change the data at the same time. To avoid such race conditions proper means have to be applied:

Full protection – the safe way

  • Mutexes and locks
    To allow both changing and reading of shared data by arbitrary threads at any time you can protect data access with use of mutexes and locks. The mutex ensures that only one thread at a time can access the data.
  • Optimization with reader/writer lock
    Data which are written rarely but read often may use this kind of optimization.

Protect only where really necessary

All synchronization means cause some kind of complexity and will have an impact on execution performance. Sometimes there are simpler possibilities to ensure proper multi threading.

  • multiple reader threads – no protection at all If it is possible for your program flow then first fully initialize shared data before reader threads can access them. As long as the data will not change while being accessed from one or more reader threads threre is no need for any synchronization.
  • Safe initialization of data – std::call_once, static variables
    Within multithreaded environments the trigger for initializing some data may come from different threads at the same time (e.g. request for a singleton instance which is created on such a request).
  • Protecting simple integral values – std::atomic
    Sometimes your shared data consists only of a single integral value (e.g. some counter, some instance pointer). Instead of having to use a separate mutex you can simply define the data as being “atomic”.