Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why the code snippet gets stuck when optimization is enabled?

There are two question about the code snippet below.

  1. When the macro(i.e. NO_STUCK_WITH_OPTIMIZATION ) is not enabled, why this code snippet gets stuck when the optimization is enabled(i.e. -O1, -O2 or -O3) whereas the program works well if the optimization is not enabled?

  2. And why the program no longer get stuck if std::this_thread::sleep_for() is added?

    MEDevel.com: Open-source for Healthcare and Education

    Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

    Visit Medevel

     #include <functional>
     #include <thread>
     #include <iostream>
     #include <chrono>
     #include <atomic>
    
     #ifdef NO_STUCK_WITH_OPTIMIZATION 
     using TYPE = std::atomic<int>;
     #else
     using TYPE = int;  //The progrom gets stuck if the optimization is enabled.
     #endif
    
     int main()
     {
         TYPE is_run{1};
         auto thread = std::thread([&is_run](){while(1==is_run){
               //std::this_thread::sleep_for(std::chrono::milliseconds(10)); //If this line is added, the program is no longer gets stuck. Why?
                                             }
             std::cout << "thread game over" << std::endl;
         });
    
         std::this_thread::sleep_for(std::chrono::seconds(1));
         is_run = 0;
         thread.join();
     }
    

>Solution :

You have a multi-threaded program. One thread does is_run = 0;.

The other thread does while(1==is_run). Although you guarantee, with a sleep (matter for another question), that the write is done before the read, you need to tell the compiler to synchronize this variable.

In C++, the simple way to make sure one thread sees the change is to use atomic<int>. If you don’t do this, the other thread might never see the change. This hiding of the change might be due to local optimization of the code at compile time, by the OS deciding not to refresh some memory page or by the hardware itself deciding the memory doesn’t need to be reloaded.

Putting the atomic variable guarantees all those systems know what you want to do. So, use it. 🙂

Lifting from the comments:

https://en.cppreference.com/w/cpp/language/memory_model#Threads_and_data_races

A program that has two conflicting evaluations has a data race unless both evaluations execute on the same thread or in the same signal handler, or
both conflicting evaluations are atomic operations (see std::atomic), or one of the conflicting evaluations happens-before another (see std::memory_order) If a data race occurs, the behavior of the program is undefined.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading