Michael Gomes
Michael Gomes

Reputation: 43

Confusing C++ Thread Behavior

I was reading some literature on C++11 threads and tried the following code:

#include "iostream"
#include "thread"

using namespace std;

class background_task{
    int data;

    int flag;

    public:
        background_task(int val):data(val),flag(data%2){}

        void operator()(void){
            int count = 0;
            while(count < 100)
            {
                if(flag)
                    cout <<'\n'<<data++;
                else
                    cout <<'\n'<<data--;
                count++;
            }
        }
};

int main(int argc , char** argv){
    std::thread T1 {background_task(2)};
    std::thread T2 {background_task(3)};
    T1.join();
    T2.join();
    return 0;
}

the output doesn't make sense given that i am running two threads so each should be printing almost together and not wait for one thread to finish to start. Instead each thread finishes and then the next thread starts, like in a synchronous fashion.Am i missing something here?

Upvotes: 2

Views: 149

Answers (5)

Awais Rafique
Awais Rafique

Reputation: 486

while(count < 10000)

Loop may be finished before starting of next thread, you can see the difference if you increase the loop or insert some sleep inside the loop.

Upvotes: 1

Arup
Arup

Reputation: 384

Try below code, modified you earlier code to show the result:

#include "iostream"
#include "thread"

using namespace std;

class background_task{
    int data;

    int flag;

    public:
        background_task(int val):data(val),flag(data%2){}

        void operator()(void){
            int count = 0;
            while(count < 10000000)
            {
                if(flag)
                    cout <<'\n'<<"Yes";
                else
                    cout <<'\n'<<"   "<<"No";
                count++;
            }
        }
};

int main(int argc , char** argv){
    std::thread T1 {background_task(2)};
    std::thread T2 {background_task(3)};
    T1.join();
    T2.join();
    return 0;
}

By the time second thread starts first thread is already done processing hence you saw what you saw.

Upvotes: 1

druckermanly
druckermanly

Reputation: 2741

Your operating system need not start the threads at the same time; it need not start them on different cores; it need not provide equal time to each thread. I really don't believe the standard mandates anything of the sort, but I haven't checked the standard to cite the right parts to verify.

You may be able to (no promises!) get the behavior you desire by changing your code to the following. This code is "encouraging" the OS to give more time to both threads, and hopefully allows for both threads to be fully constructed before one of them finishes.

#include <chrono>                                                
#include <iostream>                                              
#include <thread>                                                

class background_task {                                          
 public:                                                         
  background_task(int val) : data(val), flag(data % 2) {}        
  void operator()() {                                            
    int count = 0;                                               
    while (count < 100) {                                        
      std::this_thread::sleep_for(std::chrono::milliseconds(50));
      if (flag)                                                  
        std::cout << '\n' << data++;                             
      else                                                       
        std::cout << '\n' << data--;                             
      count++;                                                   
    }                                                            
  }                                                              
 private:                                                        
  int data;                                                      
  int flag;                                                      
};                                                               

int main() {                                                     
  std::thread T1{background_task(2)};                            
  std::thread T2{background_task(3)};                            
  T1.join();                                                     
  T2.join();                                                     
  return 0;                                                      
}       

Upvotes: 2

izlin
izlin

Reputation: 2138

In addition to Amir Rasti's answer I think it's worth mentioning the scheduler.

If you use a while(1) instead, you will see that the output isn't exactly parallel even after the two threads running "parallel". The scheduler (part of the operating system) will give each process time to run, but the time can vary. So it can be that one process will print 100 characters before the scheduler let the other process print again.

Upvotes: 1

Amir Rasti
Amir Rasti

Reputation: 768

its probably because of creating a new thread takes some time and the first thread finishes before the next one begin . and you have the choice to detach or join a thread like

 t1.detach();//don't care about t1 finishing 
 or t1.join()//wait for t1 to finish 

Upvotes: 2

Related Questions