2

What is the correct way in C to make sure that when one thread writes to a variable the other thread can read the updated value? I didn't find any answers to this despite searching and 'Questions that may already have your answer', which gave me results that weren't C, and there were a lot of them.

As far as I can tell it isn't covered in C so I would have to rely on platform specific calls but I am looking for something portable across platforms. I know I can use a lock but I think that would have some unnecessary overhead since I'm sure that one thread only needs to read from the variable and the other thread only needs to write to the variable. I want the thread reading the variable to know as soon as it was modified. Is there a correct not platform specific way to do that? Thanks

newguy
  • 617
  • 6
  • 15
  • Check for any producer-consumer questions. It does what you are asking. Ex: http://stackoverflow.com/questions/40757091/single-producer-consumer-circular-buffer-which-only-blocks-consumer/40759375#40759375 – MayurK Dec 04 '16 at 08:06
  • 1
    Volatile should be enough, if no other variables are involved. The usual issue is when multiple variables are involved, in which case operations may be performed out of order due to compiler and/or processor optimizations. – rcgldr Dec 04 '16 at 08:09
  • The PThread API provides read-write locks (http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_rwlock_unlock.html) if not a simple mutex/condition pair would do. Mutexes and conditions may also come with C11 natively. – alk Dec 04 '16 at 08:10
  • 2
    @rcgldr: I probably won't. Specifying a variable as volatile does not keep one thread from reading the variable just the moment it gets written, which might lead to unexpected result, if not to the infamous undefined behaviour. – alk Dec 04 '16 at 08:16
  • @alk - volatile is meant to be hardware safe, and atomic assuming a compatible variable type. The reading thread could either read a value just before or just after a write, but it won't get a partially updated variable. There's no synchronization between threads with this type of variable, but cache coherency means the variable will get updated properly in both threads. – rcgldr Dec 04 '16 at 08:26
  • @rcgldr: You want to emphasize "*be ... atomic assuming a **compatible** variable type*" and better be much more explicit on what this means. – alk Dec 04 '16 at 08:29
  • 1
    http://stackoverflow.com/a/25320238/6028746 – Nir Duan Dec 04 '16 at 09:58
  • 1
    @rcgldr Where in the standard is specified what a "compatible type" is and where does it say volatile variables are atomic if they are a compatible type? – Voo Dec 04 '16 at 12:53
  • @Voo - atomic "compatible type" would normally be independent of volatile, and would be platform specific, see Ni Duan's link for GCC. Since volatile is supposed to work with memory mapped hardware ports, which generally need to be atomic operations, a compiler might produce a warning if volatile was used on a non atomic type. On most platforms, integers would be atomic (like a 32 bit integer in 32 bit or 64 bit mode). Cache coherency guarantees that you don't get partial updates on atomic type variables between threads or processes (if using shared memory). – rcgldr Dec 04 '16 at 14:16
  • 2
    You need at least C11 for a portable approach. In the standard (available as a draft), you'll want to look at , and possibly also at the memory consistency model specification at 5.1.2.3 Program Execution. Oh, and volatile wouldn't work. – ninjalj Dec 04 '16 at 15:30
  • `volatile` is nowhere near enough. See [Volatile: Almost Useless for Multi-Threaded Programming](https://software.intel.com/en-us/blogs/2007/11/30/volatile-almost-useless-for-multi-threaded-programming), along with [If volatile is useless for threading, why do atomic operations require pointers to volatile data?](https://stackoverflow.com/questions/6397662/if-volatile-is-useless-for-threading-why-do-atomic-operations-require-pointers) and [When to use volatile with multi threading?](https://stackoverflow.com/questions/4557979/when-to-use-volatile-with-multi-threading?noredirect=1&lq=1) – Andrew Henle Mar 26 '18 at 09:21

1 Answers1

0

You need at least C11 for a portable approach. In the standard (available as a draft), you'll want to look at , and possibly also at the memory consistency model specification at 5.1.2.3 Program Execution. Oh, and volatile wouldn't work. – ninjalj

Right; to expand on this, one could write for example:

#include <stdatomic.h>
…
    // thread 1
    atomic_store(&variable, value);
…
    // thread 2
    value = atomic_load(&variable);
…

(You might also be interested in UNIX Portable Atomic Operations or <stdatomic.h> in GCC 4.8?)

Armali
  • 18,255
  • 14
  • 57
  • 171