6

There are two threads (t1 and t2) pinned to two different cores. They both have a shared variable which is a raw pointer to some class type. t1 only reads the pointer and t2 reads/writes the pointer. Should I declare the pointer as just volatile or atomic or both?

When t2 updates this pointer, it is fine if t1 reads the old one or new one but it should not read any intermediate value as it will cause seg fault.

balki
  • 26,394
  • 30
  • 105
  • 151
  • 5
    Unless you're on a certain platform that adds a certain extra semantic to `volatile`, `volatile` has nothing to do with threads. – R. Martinho Fernandes Apr 11 '12 at 18:35
  • 2
    As stated [volatile has nothing to do with multithreading](http://stackoverflow.com/questions/4557979/when-to-use-volatile-with-multi-threading) <- Obviously ignore the accepted answer. – Joe Apr 11 '12 at 18:38
  • Are you perhaps looking for the double-check locking pattern? http://mortoray.com/2012/02/28/double-checked-locking-why-doesnt-it-work-and-how-to-fix-it/ – edA-qa mort-ora-y Apr 11 '12 at 21:46

2 Answers2

6

volatile is useful for telling the compiler not to optimize out repeated accesses to the memory used by a variable. Obviously you'll want this if another thread could be updating the variable. The reason it's called "almost useless" is that in too many cases this is not sufficient to guarantee proper multi-threaded behavior and you'll need to look at memory fences and atomic primitive operations.

On some processor architectures such as Intel, a read or write to an integer or pointer will be atomic as long as it's properly memory aligned. See for example http://software.intel.com/en-us/forums/showpost.php?p=31711 Intel links keep changing so I wasn't able to find the definitive resource.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • >> On some processor architectures such as Intel, a read or write to an integer or pointer will be atomic as long as it's properly memory aligned. How to verify if a pointer is properly memory aligned or not? I am coding for a server application. Is it safe to assume pointer read is always atomic? – balki Apr 12 '12 at 19:14
3

volatile is useless for multithreading, so that option is out. You indeed just want an atomic variable.

GManNickG
  • 494,350
  • 52
  • 494
  • 543
  • How to declare a pointer as atomic? should I cast it into unsigned int? – balki Apr 11 '12 at 18:38
  • 3
    @balki: It depends. C++11 has built-in atomic support, so you can `#include ` and then do `std::atomic p`. But if your compiler doesn't support that, you'll have to find a different threading library to use, like Intel's TBB. – GManNickG Apr 11 '12 at 18:40
  • 1
    @balki: No. No types are guaranteed to be atomic, you have to use threading utilities. I highly recommend Intel TBB. Otherwise you'll have to write it yourself using [InterLocked*](http://msdn.microsoft.com/en-us/library/windows/desktop/ms686360%28v=vs.85%29.aspx) functions, but you should avoid doing that because it's easy to get wrong. – GManNickG Apr 11 '12 at 18:47
  • Ok. So I declared the pointer to be atomic. Since only one thread writes and other thread reads, is it possible that the variable is cached in writer's thread and not updated to main memory, so the reader thread always sees old value? – balki Apr 11 '12 at 18:59
  • @balki : `std::atomic<>` takes care of that for you. (It wouldn't be very useful otherwise. ;-]) – ildjarn Apr 11 '12 at 19:01
  • @balki For some definition of "atomic". Historically, atomic would simply mean that you see all or nothing of a change, but not guarantee that you necessarily see a change, even if there is one. There's been some semantic drift, however, and it is widespread to use the word _atomic_ to mean that access is synchronized between threads; that when one thread updates the value, all other threads will see the updated value (provided that their access is also atomic). The C++ standard uses atomic in this second sense. – James Kanze Apr 11 '12 at 19:04
  • According to the question, you can actually get away with relaxed memory semantics ( http://bartoszmilewski.com/2008/12/01/c-atomics-and-memory-ordering/ , but also look at the next post: http://bartoszmilewski.com/2008/12/23/the-inscrutable-c-memory-model/ ). – Max Lybbert Apr 11 '12 at 19:13
  • Without C++ 11 you _need_ volatile to do proper multithreaded atomics (and you must rely on processor guarantees as well). – edA-qa mort-ora-y Apr 11 '12 at 21:45
  • 1
    @edA-qamort-ora-y: How so? Whatever processor/platform specific functionality you use will take care of everything. It's old news that `volatile` isn't useful for multithreading. – GManNickG Apr 11 '12 at 21:50
  • Pre C++11 atomics there is no other way to tell the compiler (gcc at least) not to optimize away access to a variable other than `volatile`. The compiler can avoid additional loads on the value if it deems it can't be changed (since it is thread agnostic it considers only the current thread). The `volatile` forces it to reload the variable every time it is read. The `volatile` is of course not enough to ensure other memory ordering, so it alone is not enough, but definitely necessary. – edA-qa mort-ora-y Apr 11 '12 at 22:18
  • 1
    @edA-qamort-ora-y: "The `volatile` is of course not enough to ensure other memory ordering, so it alone is not enough" right, we agree here. But once you add in the memory ordering *you also implicitly add the effects of `volatile`*. When you use `InterLockedExchange`, for example, the compiler already knows that reading or writing the variable should be treated as an observable effect, so `volatile` is not needed. – GManNickG Apr 11 '12 at 22:27
  • Sure, if you have an API that provides this ability you don't need volatile. If you don't have the API, or wish to do lower level tuning, you have to add the volatile yourself. For example on x86_64 a normal variable read is sufficient, thus no API needed, but you do need to mark it volatile to ensure the compiler generates that load instruction. – edA-qa mort-ora-y Apr 11 '12 at 22:42
  • 1
    @edA-qamort-ora-y: It's enough to make it atomic (if its properly aligned), sure, but does it have the proper fences? – GManNickG Apr 11 '12 at 22:49