Fixing DCLP only with volatile

189 views Asked by At

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!

2

There are 2 answers

4
deviantfan On BEST ANSWER

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.

0
James On

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.