开发者

Is the volatile the correct way to inform the compiler about concurrent access to a variable

开发者 https://www.devze.com 2023-02-23 06:11 出处:网络
While doing concurrent programming I need to tell the compiler/optimizer that it may not cache the value of a variable, that is, it may change at any time.I am currently using the volatile keyword, bu

While doing concurrent programming I need to tell the compiler/optimizer that it may not cache the value of a variable, that is, it may change at any time. I am currently using the volatile keyword, but I am wondering if this is actually correct?

The standard states that volatile accesses may not be reordered, like IO calls, but 开发者_StackOverflow中文版I actually don't care about the ordering at all, I care about the contents. Is there anything in the standard that would clarify that a volatile must be loaded every time it is accessed?

More so, in this case I don't even care if it is reordered. I use fences/atomic operations to guarantee any ordering which I need.

Also, in C++0x, will using atomic<T> automatically give this same loading guarantee (if I call load)? Or will I nonetheless have to mark the variable as volatile?

IMPORTANT I'm not interested in locking a section of code. I already use fences to ensure ordering. I'm talking specifically about the access to a single fundamental like int (assume atomic on the platform I'm on). That is, I need to specifically tell the GCC optimizer that variable a should not be cached in any way, so that if used in a loop the appropriate load instruction must be called every single time.


If volatile is not correct, what is the correct way of doing this? I am using GCC and not using C++0x at the moment.

ANSWER: Basically pre C++0x there is nothing to force a reload, and reload may not even be enough on certain architectures. volatile strongly implies that the variable should be reloaded, and will work on many architectures, and while not the correct answer, is the only available option at the moment.


There are already many questions about volatile, but I have not seen one that addresses specifically what I am asking: the proper way to mark a variable for concurrent access.


Congratulations on figuring so many details out for yourself. Yes, volatile is not particularly useful for multithreaded programming, and constructs provided by your platform-specific multithreading library (e.g. pthreads) should always be preferred.

Specifically, you should use a read-write lock: an object which can be unlocked for one writer at a time to the exclusion of readers and other writers, or unlocked by multiple readers to the exclusion of any writer. This will be included in any threading API.

C++0x atomic<T> does solve the problem, you should never need volatile unless you are writing a device driver. However atomic is at a lower level and you'll probably be better off with the read-write lock abstraction.


No, volatile has nothing to do with threads.

EDIT

volatile is useless for multithreaded programming. It does not provide any synchronization, it does not create memory fences, nor does it ensure the order of execution of operations. It does not make operations atomic. It does not make your code magically thread safe. volatile may be the single-most misunderstood facility in all of C++. See this, this and this for more information about volatile

On the other hand, volatile does have some use that may not be so obvious. It can be used much in the same way one would use const to help the compiler show you where you might be making a mistake in accessing some shared resource in a non-protected way. This use is discussed by Alexandrescu in this article.

volatile is specifically used for is interfacing with memory-mapped hardware, signal handlers and the setjmp machine code instruction.

What to use for concurrent access?

You actually need some mechanism that was developed specifically for that purpose. For example mutexes, and semaphores.


As far as I understand, prior to atomic<T>, there is no standard way 'to mark a variable for concurrent access' in C++. Instead, you must use platform-specific functions to achieve the results you want, like the InterlockedXXX functions on Windows for example.


No, volatile isn't intended for concurrent use and is not suitable for making it concurrency-safe at all. Volatile will prevent the compiler from caching the variable, but this is not enough to make it thread-safe. Most platforms come with concurrency extensions, but C++03 does not have anything about it in it's Standard.

If you are using atomic operations, you don't need volatile. As far as I know, for both MSVC and GCC, atomic operations compile to specific instructions and they will not cache atomically accessed variables. If you look at the source code for MSVC's std::shared_ptr, they do not mark the reference counts as volatile, but instead just use atomic operations.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号