Search code examples
c++11mutexcondition-variablestdthreaddata-race

C++11 std::threads not exiting


Could you please check the following code which is not exiting even after condition becomes false?

I'm trying to print numbers from 1 to 10 by first thread, 2 to 20 by second thread likewise & I have 10 threads, whenever count reaches to 100, my program should terminate safely by terminating all threads. But that is not happening, after printing, it stuck up and I don't understand why?

Is there any data race? Please guide.

#include<iostream>
#include<vector>
#include<thread>
#include<mutex>
#include<condition_variable>

std::mutex mu;
int count=1;
bool isDone = true;
std::condition_variable cv;

void Print10(int tid)
{
        std::unique_lock<std::mutex> lock(mu);
        while(isDone){
                cv.wait(lock,[tid](){ return ((count/10)==tid);});
                for(int i=0;i<10;i++)
                        std::cout<<"tid="<<tid<<" count="<<count++<<"\n";
                isDone = count<100;//!(count == (((tid+1)*10)+1));
                std::cout<<"tid="<<tid<<" isDone="<<isDone<<"\n";
                cv.notify_all();
        }
}
int main()
{
        std::vector<std::thread> vec;

        for(int i=0;i<10;i++)
        {
                vec.push_back(std::thread(Print10,i));
        }

        for(auto &th : vec)
        {
                if(th.joinable())
                        th.join();
        }

}

Solution

  • I believe the following code should work for you

        #include<iostream>
        #include<vector>
        #include<thread>
        #include<mutex>
        #include<condition_variable>
        
        using namespace std;
        mutex mu;
        int count=1;
        bool isDone = true;
        condition_variable cv;
         
        void Print10(int tid)
        {
            unique_lock<std::mutex> lock(mu);
            
            // Wait until condition --> Wait till count/10 = tid
            while(count/10 != tid)
                cv.wait(lock);
            
            // Core logic 
            for(int i=0;i<10;i++)
                cout<<"tid="<<tid<<" count="<<count++<<"\n";
                    
            // Release the current thread thus ensuring serailization
            cv.notify_one();
        }
        int main()
        {
            std::vector<std::thread> vec;
        
            for(int i=0;i<10;i++)
            {
                vec.push_back(std::thread(Print10,i));
            }
        
            for(auto &th : vec)
            {
                if(th.joinable())
                    th.join();
            }
                
            return 0;
        }