3

I am reading the article "C++ and the Perils of Double-Checked Locking" which explains the problems in DCLP.

The second part of the article (where the link forwards) shows how to try and solve DCLP with merely C/C++ volatile (which from what I know, it is impossible). In the article the writers explain how to do that (last example is number 11), but than they write:

Unfortunately, all this does nothing to address the first problem—C++'s abstract machine is single threaded, and C++ compilers may choose to generate thread-unsafe code from source like that just mentioned, anyway. Otherwise, lost optimization opportunities lead to too big an efficiency hit. After all this, we're back to square one. But wait, there's more—more processors.

Which means (if I understand correctly), that it doesn't matter how well we will use volatile, it won't work because "C++'s abstract machine is single threaded, and C++ compilers may choose to generate thread-unsafe code from source like that just mentioned"

But what does that mean "C++'s abstract machine is single threaded"?!

Why does the above examples with all of those volatiles won't prevent the reordering?

Thanks!

TCS
  • 5,790
  • 5
  • 54
  • 86

2 Answers2

2

Since C++11, your bold marked sentence isn´t true anymore.

What it meant in the past:
The OS/device may support multiple threads, including functions to start them etc..
C++ compilers on the other hand etc. "think" of single thread environments, and are not aware of possible problems when using multiple threads. A thread start isn´t anything else but a normal function call for them, and that the OS does something strange to the process because of that call is neither known nor interesting.

Code reordering in single thread environments is possible as long as the reordered code parts are independent from each other (eg. the order how a variable is written/read to/from makes code using this variable dependent). In a multithread environment, the compiler can´t possibly know if and when a variable is influenced by another thread...

Now, in C++11/C++14, there is OS-independent support
for preventing optimizations breaking threaded code.

deviantfan
  • 11,268
  • 3
  • 32
  • 49
  • 3
    Worth mentioning that with C++11's `std::atomic`s and other concurrency support, it has finally become possible to write safe double-checked locking code in standard C++ – without the use of `volatile`. – 5gon12eder Jun 13 '15 at 10:48
  • 2
    It is true that since C++11 the standard is aware of threading. On the other hand the programmer is still obligated to avoid UB. volatile, according to the standard, does not provide particularly strong guarantees regarding threading. volatile accesses can be reordered generously. – usr Jun 13 '15 at 10:59
  • Yes, UB is still UB, nobody said something else. Wrong code is wrong code, independent of threading support. "If" the downvote was from you because of that, it´s just funny. (Also, I didn´t even mention `volatile` in my answer) – deviantfan Jun 13 '15 at 11:02
  • I did downvote *because* you didn't mention volatile. The question is about it. – usr Jun 13 '15 at 11:27
0

It means that the writes performed by one thread are always visible to itself immediately and will have the same logical result as though the code was not reordered by either the compiler or CPU, even though that might have happened.

What was broken was how those writes appeared to other threads who share the same data space. That was fixed in C++11.

It also gave a slightly different meaning to const and mutable. Making a class member mutable is no longer the kludge it used to be, now use it when a member can be modified in a thread safe manner, i.e. Any changes are visible to other threads in a logically consistent way. E.g. It's perfectly fine to make a std::mutex or std::atomic mutable, but not a plain int.

James
  • 9,064
  • 3
  • 31
  • 49