how to use volatile key word?

Ä

ä¼è™Ž

how to use volatile key word?

Assume I have a global variable shared by two or more tasks. Do I need to declare it as volatile?

When will a non-volatile global variable be written back to memory from a register copy? Before a function call? Or before the return statement?
 
V

Victor Bazarov

how to use volatile key word?

Assume I have a global variable shared by two or more tasks. Do I
need to declare it as volatile?

'volatile' usually means that the object's value can be changed at any
moment by some mechanism outside of your program control. When you have
a global variable shared between parts of *your program*, that's all
under your control, and hence doesn't need to be declared 'volatile'.
When will a non-volatile global variable be written back to memory
from a register copy? Before a function call? Or before the return
statement?

Side effects (like changing memory) happen at "sequence points", within
the same thread. Shared [between threads] data need to be protected
better, and there are mechanisms for that - see "atomic operations" and
"synchronization". That's all in theory, of course. Do you have a
particular problem?

V
 
J

Juha Nieminen

Paavo Helde said:
Volatile is meant to be used for accessing memory-mapped hardware, if you
are not writing device drivers or such you can just forget about it. It is
neither needed nor sufficient for portable thread synchronisation.

'volatile' might not be sufficient for thread synchronization nor atomicity,
but it can certainly make a difference in a multithreaded program.

In a program I had a case where I was just reading an integral from one
thread that was changed by another thread to signal a minor, unimportant
effect (namely something related to updating the UI). This did not require
full-fledged locking (which would have made it needlessly expensive) because
if the integral had a wrong value for a split second, that wasn't really
a catastrophical event.

However, 'volatile' had a major impact on that integral. Without it, the
other thread was not seeing the changes immediately, causing a noticeable
delay (it was a situation where the thread that was setting that integral
did it inside a loop, and the compiler was optimizing the updating of the
variable in such a way that the actual writing to the extern variable was
delayed to be after the loop). With 'volatile' the variable was always
updated immediately.
 
M

Mark

Volatile is meant to be used for accessing memory-mapped hardware, if you
are not writing device drivers or such you can just forget about it. It is
neither needed nor sufficient for portable thread synchronisation.

I'd say the volatile keywork is not sufficient but it is necessary in
some circumstances.

This page does show cases where use of the volatile keyword is
necessary.
 
I

Ian Collins

'volatile' might not be sufficient for thread synchronization nor atomicity,
but it can certainly make a difference in a multithreaded program.

In a program I had a case where I was just reading an integral from one
thread that was changed by another thread to signal a minor, unimportant
effect (namely something related to updating the UI). This did not require
full-fledged locking (which would have made it needlessly expensive) because
if the integral had a wrong value for a split second, that wasn't really
a catastrophical event.

Did you measure? In the absence of contention, the impact of locking
should be close to none.
 
J

Juha Nieminen

Paavo Helde said:
Out of curiosity - did you measure how much the "needlessly expensive"
locking was slower than using a volatile? I'm asking because I find myself
often in urge to invent all kind of clever tricks to bypass proper locking.

No, but it was enough that the options were between writing 'volatile'
and several lines of code using a non-standard library to implement proper
locking, so the choice was rather clear to me.

(In C++11 it might have been enough to declare the integral to be atomic,
and it would probably have been equally fast and fully synchronized. However,
I did not have C++11 at my disposal at that time.)
 
J

Juha Nieminen

Ian Collins said:
Did you measure? In the absence of contention, the impact of locking
should be close to none.

Locking is always expensive, even if no thread has to wait at any point.

That's the very reason why so much research is being done on lock-free
containers and atomic operations.

Anyways, if the choice is between writing 'volatile' and writing several
lines of code to implement locking in a situation where locking is not
needed, the choice is pretty clear.
 
I

Ian Collins

Locking is always expensive, even if no thread has to wait at any point.

That's the very reason why so much research is being done on lock-free
containers and atomic operations.

Anyways, if the choice is between writing 'volatile' and writing several
lines of code to implement locking in a situation where locking is not
needed, the choice is pretty clear.

Until you have to run on a multi-core system....
 
M

Mark

Not sure what you mean, for C and C++ I see only discussion about memory-
mapped hardware. The examples about multi-thread synchronization with
volatile are talking about Java and C# where this keyword apparently means
something different.

As I understand it there is still a risk of the unsafe opimizations
which the volatile keyword would prevent.
 
L

Luca Risolia

Locking is always expensive, even if no thread has to wait at any point.

That's the very reason why so much research is being done on lock-free
containers and atomic operations.

Globally speaking, with regard to the C++11 standard, atomic types may
use non-blocking locks in the implementation. The only exception is
std::atomic_flag, which is guaranteed not to use locks. This means that
lock-free data structures and are not necessarily wait-free data structures.

Writing wait-free data structures is extremely hard and even when you
get them right, you should make sure that the benefit outweighs the
cost, since the group of atomic operations used to implement them can be
much slower than non-atomic counterpart. In other words, the main reason
to write lock-free and wait-free code is to increase the potential for
concurrency, but it may well decrease overall performance.

For these reasons it's important to identify the relevant performance
aspect and profile various alternatives on the target platforms before
deciding.
 
G

Gerhard Fiedler

Mark said:
As I understand it there is still a risk of the unsafe opimizations
which the volatile keyword would prevent.

While that's true, the memory barriers that come with synchronized
processor instructions, synchronization library functions/objects or the
new C++ synchronization mechanisms prevent these unsafe optimizations
also. That's why volatile is not necessary if you use these.

Gerhard
 
D

Dombo

Op 28-Jun-12 7:55, Juha Nieminen schreef:
Locking is always expensive, even if no thread has to wait at any point.

It depends; for example on Windows critical sections have minimal
overhead on single core systems when there is no thread contention.
Basically it boils down to a (sort-of) atomic test-and-set instruction,
and only when the test fails it makes the (expensive) jump to kernel
mode to halt the thread. On multi-core systems the test-and-set
instruction gets a LOCK prefix to synchronize across cores which makes
it a bit more expensive. OTOH if you use just 'volatile' variables to
synchronize across threads in on x86 multi-core environments you would
need the LOCK prefix as well for read-modify-write operations.
That's the very reason why so much research is being done on lock-free
containers and atomic operations.

Anyways, if the choice is between writing 'volatile' and writing several
lines of code to implement locking in a situation where locking is not
needed, the choice is pretty clear.

In that case you might even get away with leaving out 'volatile' as well.
 
D

Dombo

Op 28-Jun-12 21:16, Ian Collins schreef:
On reflection, possibly not a lot. volatile should keep the variable out
of caches and visible to the other cores.

I don't know what the C++ 11 standard says about this but, on VS2010 it
does nothing special to keep volatile variables out of the cache.
 
8

88888 Dihedral

Juha Nieminenæ–¼ 2012å¹´6月28日星期四UTC+8下åˆ1時53分40秒寫é“:
Well, this is the old joke of C with switches and cases not dupliating
the key value in cores to execute in parallel.


No, but it was enough that the options were between writing 'volatile'
and several lines of code using a non-standard library to implement proper
locking, so the choice was rather clear to me.

(In C++11 it might have been enough to declare the integral to be atomic,
and it would probably have been equally fast and fully synchronized. However,
I did not have C++11 at my disposal at that time.)



Juha Nieminenæ–¼ 2012å¹´6月28日星期四UTC+8下åˆ1時53分40秒寫é“:
No, but it was enough that the options were between writing 'volatile'
and several lines of code using a non-standard library to implement proper
locking, so the choice was rather clear to me.

(In C++11 it might have been enough to declare the integral to be atomic,
and it would probably have been equally fast and fully synchronized. However,
I did not have C++11 at my disposal at that time.)

I think MS did sense the need for multi-core programming in C#.

But C++ is getting old to have a kid in the C family.
 
C

Cong Wang

'volatile' usually means that the object's value can be changed at any
moment by some mechanism outside of your program control. When you have
a global variable shared between parts of *your program*, that's all
under your control, and hence doesn't need to be declared 'volatile'.

Right...

Also check this doc:
http://www.kernel.org/doc/Documentation/volatile-considered-harmful.txt

even though it is for kernel, it applies to user-space applications as
well.

Thanks.
 
M

Mark

While that's true, the memory barriers that come with synchronized
processor instructions, synchronization library functions/objects or the
new C++ synchronization mechanisms prevent these unsafe optimizations
also. That's why volatile is not necessary if you use these.

We can't all rely on new features. I have to maintain code that needs
to work on a large variety of different compilers (including quite old
ones).
 
G

Gerhard Fiedler

Mark said:
We can't all rely on new features. I have to maintain code that needs
to work on a large variety of different compilers (including quite old
ones).

FWIW, I wasn't talking about new features /only/. Working
implementations of pthread and compiler support for synchronized atomics
have been around since long before C++11.

Gerhard
 
G

Gerhard Fiedler

Scott said:
And working code using volatile has been around since long before
pthreads.

So what? It seems to get more and more difficult to make a point that
uses more than two sentences or 12 words... :)

The line of arguments here is (I'm trying to stay under 12 words):

(A) "volatile" is needed to prevent unsafe compiler optimizations.
(B) Other methods also prevent unsafe optimizations.
(A) I can't use these other methods because I can't use C++11.
(B) Many of those other methods don't need C++11 features.

I couldn't put the whole chain in 12 words, but maybe this shortened
summary helps illustrate anyway why the fact that in some situations
volatile works has nothing to do with this sub-thread.

Gerhard
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top