Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it useful to mark variables as volatile if they are shared across threads? [duplicate]

Notice!

I'm obviously failing to make my point clearly to everyone here, and it's incredibly frustrating. My goal was to dispel the myth that volatile is effectively a no-op, that it does nothing. I was not trying to state that it should be used, that it is essential, that it is not redundant, etc.

I have shown that volatile does still do a thing. I concede that it is redundant under certain circumstances, and that the multi-threaded example was a poor choice.

I am also not trying to hide the fact that my answer's initial revisions contained errors. But this Q&A is not even coming close to fulfilling its intended purpose. To that end, I think it's time to chuck it away.

Thanks to Kerrek and T.C. for their insights. I just don't think their responses fit the question that I wanted to ask. I'm sure that's my fault for asking it poorly.

Therefore I am abandoning it! And closing it as a duplicate of the question not that it was intended as, but that it has been interpreted as.

Cheers! (& hth.)

I am writing to a variable in one thread and reading from it in another. I have been told that volatile is completely useless for this and that I do not need to use it in this day and age unless I am working with hardware.

int x = 0;
void thread1()
{
   while (true) {
      sleep(1);
      if (x > 0)
         break;
   }
}

void thread2()
{
   while (true) {
      sleep(1);
      x++;
   }
}

Do I gain anything by using volatile in this case?
And how about if x is not a simple int but a class type?

like image 809
Lightness Races in Orbit Avatar asked Nov 30 '22 00:11

Lightness Races in Orbit


1 Answers

You have been told correctly, volatile is not useful for inter-thread communication. Don't use it for that purpose. It does not provide synchronization and leaves your code with data races. Conversely, when synchronizing access to shared state correctly, you do not need volatile.

The correct code that Does What You Mean uses atomic variables for the shared state or protects the shared state with a mutex, and the shared state will be observed correctly by all threads. For example:

#include <atomic>

std::atomic<int> x = 0;

void thread1()
{
   while (true) {
      sleep(1);
      if (x > 0)
         break;
   }
}

void thread2()
{
   while (true) {
      sleep(1);
      x++;
   }
}

At no point is there any need for volatile.

Note that volatile may be useful within a thread to enforce that a loop that otherwise has no side effects is evaluated:

// Spend some time
for (volatile int i = 0; i != LARGE_NUMBER; ++i)
{ /* do nothing */ }

// or even:
for (int i = 0; const_cast<volatile int &>(i) != LARGE_NUMBER; ++i) {}
like image 93
Kerrek SB Avatar answered Dec 04 '22 01:12

Kerrek SB