Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c++ volatile multithreading variables

Tags:

c++

volatile

I'm writing a C++ app.

I have a class variable that more than one thread is writing to.

In C++, anything that can be modified without the compiler "realizing" that it's being changed needs to be marked volatile right? So if my code is multi threaded, and one thread may write to a var while another reads from it, do I need to mark the var volaltile?

[I don't have a race condition since I'm relying on writes to ints being atomic]

Thanks!

like image 865
anon Avatar asked Feb 26 '10 12:02

anon


People also ask

What is volatile variable in multithreading?

Volatile keyword is used to modify the value of a variable by different threads. It is also used to make classes thread safe. It means that multiple threads can use a method and instance of the classes at the same time without any problem. The volatile keyword can be used either with primitive type or objects.

Can volatile be a variable in C?

C's volatile keyword is a qualifier that is applied to a variable when it is declared. It tells the compiler that the value of the variable may change at any time--without any action being taken by the code the compiler finds nearby.

Are volatile variables thread safe?

Unlike synchronized methods or blocks, it does not make other threads wait while one thread is working on a critical section. Therefore, the volatile keyword does not provide thread safety when non-atomic operations or composite operations are performed on shared variables.

Where volatile variables are stored in C?

Volatile Keyword means that the variable will be loaded from its memory location every time you are using this variable, the compiler will never depend on the temporary value stored in the internal CPU Registers.


4 Answers

C++ hasn't yet any provision for multithreading. In practice, volatile doesn't do what you mean (it has been designed for memory adressed hardware and while the two issues are similar they are different enough that volatile doesn't do the right thing -- note that volatile has been used in other language for usages in mt contexts).

So if you want to write an object in one thread and read it in another, you'll have to use synchronization features your implementation needs when it needs them. For the one I know of, volatile play no role in that.

FYI, the next standard will take MT into account, and volatile will play no role in that. So that won't change. You'll just have standard defined conditions in which synchronization is needed and standard defined way of achieving them.

like image 188
AProgrammer Avatar answered Sep 28 '22 12:09

AProgrammer


Yes, volatile is the absolute minimum you'll need. It ensures that the code generator won't generate code that stores the variable in a register and always performs reads and writes from/to memory. Most code generators can provide atomicity guarantees on variables that have the same size as the native CPU word, they'll ensure the memory address is aligned so that the variable cannot straddle a cache-line boundary.

That is however not a very strong contract on modern multi-core CPUs. Volatile does not promise that another thread that runs on another core can see updates to the variable. That requires a memory barrier, usually an instruction that flushes the CPU cache. If you don't provide a barrier, the thread will in effect keep running until such a flush occurs naturally. That will eventually happen, the thread scheduler is bound to provide one. That can take milliseconds.

Once you've taken care of details like this, you'll eventually have re-invented a condition variable (aka event) that isn't likely to be any faster than the one provided by a threading library. Or as well tested. Don't invent your own, threading is hard enough to get right, you don't need the FUD of not being sure that the very basic primitives are solid.

like image 37
Hans Passant Avatar answered Sep 28 '22 11:09

Hans Passant


volatile instruct the compiler not to optimize upon "intuition" of a variable value or usage since it could be optimize "from the outside".

volatile won't provide any synchronization however and your assumption of writes to int being atomic are all but realistic!

I'd guess we'd need to see some usage to know if volatile is needed in your case (or check the behavior of your program) or more importantly if you see some sort of synchronization.

like image 32
Francis Boivin Avatar answered Sep 28 '22 10:09

Francis Boivin


I think that volatile only really applies to reading, especially reading memory-mapped I/O registers.

It can be used to tell the compiler to not assume that once it has read from a memory location that the value won't change:

while (*p)
{
  // ...
}

In the above code, if *p is not written to within the loop, the compiler might decide to move the read outside the loop, more like this:

cached_p=*p
while (cached_p)
{
  // ...
}

If p is a pointer to a memory-mapped I/O port, you would want the first version where the port is checked before the loop is entered every time.

If p is a pointer to memory in a multi-threaded app, you're still not guaranteed that writes are atomic.

like image 31
quamrana Avatar answered Sep 28 '22 10:09

quamrana