title: Is mutex needed to synchronize a simple flag between pthreads?
body: <p>Let's imagine that I have a few worker threads such as follows:</p>
  
  <pre><code>while (1) {
      do_something();
  
      if (flag_isset())
          do_something_else();
  }
  </code></pre>
  
  <p>We have a couple of helper functions for checking and setting a flag:</p>
  
  <pre><code>void flag_set()   { global_flag = 1; }
  void flag_clear() { global_flag = 0; }
  int  flag_isset() { return global_flag; }
  </code></pre>
  
  <p>Thus the threads keep calling <code>do_something()</code> in a busy-loop and in case some other thread sets <code>global_flag</code> the thread also calls <code>do_something_else()</code> (which could for example output progress or debugging information when requested by setting the flag from another thread).</p>
  
  <p>My question is: <strong>Do I need to do something special to synchronize access to the global_flag? If yes, what exactly is the minimum work to do the synchronization in a portable way?</strong></p>
  
  <p>I have tried to figure this out by reading many articles but I am still not quite sure of the correct answer... I think it is one of the following:</p>
  
  <h2>A: No need to synchronize because setting or clearing the flag does not create race conditions:</h2>
  
  <p>We just need to define the flag as <code>volatile</code> to make sure that it is really read from the shared memory every time it is being checked:</p>
  
  <pre><code>volatile int global_flag;
  </code></pre>
  
  <p>It might not propagate to other CPU cores immediately but will sooner or later, guaranteed.</p>
  
  <h2>B: Full synchronization is needed to make sure that changes to the flag are propagated between threads:</h2>
  
  <p>Setting the shared flag in one CPU core does not necessarily make it seen by another core. We need to use a mutex to make sure that flag changes are always propagated by invalidating the corresponding cache lines on other CPUs. The code becomes as follows:</p>
  
  <pre><code>volatile int    global_flag;
  pthread_mutex_t flag_mutex;
  
  void flag_set()   { pthread_mutex_lock(flag_mutex); global_flag = 1; pthread_mutex_unlock(flag_mutex); }
  void flag_clear() { pthread_mutex_lock(flag_mutex); global_flag = 0; pthread_mutex_unlock(flag_mutex); }
  
  int  flag_isset()
  {
      int rc;
      pthread_mutex_lock(flag_mutex);
      rc = global_flag;
      pthread_mutex_unlock(flag_mutex);
      return rc;
  }
  </code></pre>
  
  <h2>C: Synchronization is needed to make sure that changes to the flag are propagated between threads:</h2>
  
  <p>This is the same as <strong>B</strong> but instead of using a mutex on both sides (reader &amp; writer) we set it in only in the writing side. Because the logic does not require synchronization. we just need to synchronize (invalidate other caches) when the flag is changed:</p>
  
  <pre><code>volatile int    global_flag;
  pthread_mutex_t flag_mutex;
  
  void flag_set()   { pthread_mutex_lock(flag_mutex); global_flag = 1; pthread_mutex_unlock(flag_mutex); }
  void flag_clear() { pthread_mutex_lock(flag_mutex); global_flag = 0; pthread_mutex_unlock(flag_mutex); }
  
  int  flag_isset() { return global_flag; }
  </code></pre>
  
  <p>This would avoid continuously locking and unlocking the mutex when we know that the flag is rarely changed. We are just using a <em>side-effect</em> of Pthreads mutexes to make sure that the change is propagated.</p>
  
  <h2>So, which one?</h2>
  
  <p>I think A and B are the obvious choices, B being safer. But how about C?</p>
  
  <p>If C is ok, is there some other way of forcing the flag change to be visible on all CPUs?</p>
  
  <p>There is one somewhat related question: <a href="https://stackoverflow.com/questions/3208060/does-guarding-a-variable-with-a-pthread-mutex-guarantee-its-also-not-cached">Does guarding a variable with a pthread mutex guarantee it&#39;s also not cached?</a> ...but it does not really answer this.</p>