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?
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) {}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With