3

Given the following scenario:

  • 2 Threads (no more, no less)
  • A shared variable (let's say a void *)
  • One thread writes to the variable ONLY once (this is guaranteed)
  • And the other thread is responsible for reading the variable

Is it thread safe to have the reader thread check for null of the variable? Explicitly in a C program?

Example code:

Thread 1:

void initOnStartup()
{
   ptr = malloc(10);
}

Thread 2:

void waitingForValue()
{
  while(!ptr);
}
bhawley
  • 395
  • 1
  • 3
  • 13
  • Yes, your code is thread-safe. The reader-thread will not continue execution until the pointer has been assigned with a valid memory address by the writer-thread (in other words, `ptr` will not attain some "half valid" value). This, under the assumption that `ptr` is initialized to `NULL` before the threads are created. To be on the safe side, check the generated dis-assembly and make sure that a single operation is used for storing the return-value into `ptr`. – barak manos Aug 10 '15 at 19:23
  • rather than run a risk that some future maintenance to the code will change the current execution flow, use a mutex, locked before modifying the variable and unlocked afterwards. – user3629249 Aug 10 '15 at 19:46
  • The question isn't how to make this thread safe, it's IF it is thread safe the way it is. – bhawley Aug 10 '15 at 19:50

3 Answers3

3

No, as the assignment = operation is not atomic.

Cloud
  • 18,753
  • 15
  • 79
  • 153
  • But the assignment operation **IS**, and that's what matters (i.e., the reader will not continue execution until the pointer has been assigned by the writer). – barak manos Aug 10 '15 at 19:10
  • @barakmanos But only for certain types, and it's OS-dependent. http://stackoverflow.com/questions/8290768/is-assignment-operator-atomic Also, there is nothing in the C standard guaranteeing it: http://stackoverflow.com/questions/879077/is-changing-a-pointer-considered-an-atomic-action-in-c – Cloud Aug 10 '15 at 19:11
  • Your notion about incrementation is irrelevant, because it is **not the same case as assignment**. Incrementation is indeed not an atomic operation, since you have to load (read from) the variable and then store (write into) it. – barak manos Aug 10 '15 at 19:12
  • The question is, whether the assignment of a pointer is atomic. I think it is not guaranteed. – followed Monica to Codidact Aug 10 '15 at 19:13
  • @barakmanos I know, I'm just mentioning a similar example so my answer isn't a bleak one-line answer. – Cloud Aug 10 '15 at 19:13
  • The question is, **is it safe or not**. Regardless of what operation is performd, the reader thread will not continue until the pointer has been assigned, and the pointer is not going to be "partially assigned" at any point (i.e., either it is `NULL` or it is a valid memory address returned by `malloc`). – barak manos Aug 10 '15 at 19:14
  • Incrementation is not similar to assignment, in particularly in the context of this question! Yes, they ask that kind of stuff on job-interviews, but if you infer from those questions into this one, then you won't pass the test. – barak manos Aug 10 '15 at 19:15
  • @Dogbert So, because other operations across the program are occurring and possibly overwriting the registries of threads 1 and 2, you can't guarantee that this is thread safe? I'm I understanding your answer correctly? – bhawley Aug 10 '15 at 19:57
  • 1
    @bhawley You cannot guarantee that when you read the value of `ptr`, it is correct. There are cases where the assignment is incomplete, depending on the system. – Cloud Aug 10 '15 at 20:13
  • 2
    Assignment is *not* atomic (Even in practice it may be atomic -- such as aligned reads/writes in x86. But C is not x86 specific). If one thread is writing and (other) one or more threads are reading the same, then it's *not* safe, which is the case here. I am not sure on what basis you assert it "the assignment operation **IS**" atomic. – P.P Aug 10 '15 at 20:30
3

It is not atomic. Newer versions of C (and c++) provide the following. http://en.cppreference.com/w/c/atomic/atomic_store

void atomic_store( volatile A* obj , C desired); // (since C11)
void atomic_store_explicit( volatile A* obj, C desired, memory_order order ); // (since C11)
Robert Jacobs
  • 3,266
  • 1
  • 20
  • 30
2

The answer is there: Is changing a pointer considered an atomic action in C? Unfortunately it isn't. Think of far pointers on 16 bit x86 platforms.

Community
  • 1
  • 1