Reputation: 3154
I have a really simple program that is giving me an exception I don't understand. I have a C++ app written in Visual Studio Express 2012 for Desktop.
I created a multithreaded application where I have 2 threads, one calls one person class, the other calls another car class.
When I use the thread.join() I don't get the exception, but I don't get the desired output. When I comment out the thread.join() I get the exception, but I also get the desired output.
The exception being: enter image description here
I'm just trying to have two threads execute and process at the same time. Both the person and car class has a method invoked that repeats 10 times with a thread sleep and all it does is print a string "started walking" for the person class and "started driving" for the car class and the main thread just has "Main waiting..."
So the output of the program is:
started walking
started driving
started walking
started driving
main waiting...
started walking
started driving
started walking
started driving
main waiting...
etc. which is what I want.
If I uncomment the join method I get this output:
started walking
started walking
(repeat 8 more times)
started driving
started driving
(repeat 8 more times)
Main waiting..
Main waiting..
(repeat 8 more times)
and this is not what I want.
How can I have this app execute without that exception without using the join() method?
As an FYI, here's the sample code I created below:
Here's the main method that starts the program.
include <iostream>
#include <thread>
#include <chrono>
#include "person.h"
#include "car.h"
int count1 = 0;
int count2 = 0;
int main()
{
person p1;
thread t1(&person::startWalking, p1);
if(t1.joinable())
{
//t1.join();
}
car c1;
thread t2(&car::startDriving, c1);
if(t2.joinable())
{
//t2.join();
}
for(int x = 0; x < 10; x++)
{
std::cout<<"Main waiting...\n";//<<std::endl;
}
std::this_thread::sleep_for(std::chrono::milliseconds(5000));
return 0;
}
Here's the person.cpp file:
#include "person.h"
person::person(void)
{
}
person::~person(void)
{
}
void person::startWalking()
{
for(int x = 0; x < 10; x++)
{
cout<<"Started Walking.\n";
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
}
void person::stopWalking()
{
cout<<"Stopped Walking.\n";
}
Here's the car.cpp file:
#include "car.h"
using namespace std;
car::car(void)
{
}
car::~car(void)
{
}
void car::startDriving()
{
for(int x = 0; x< 10; x++)
{
std::cout<<"started driving\n.";
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
}
Upvotes: 1
Views: 2101
Reputation: 470
First of all, the document reads that If the thread is joinable when destroyed, terminate() is called.
, so if you comment the thread.join() and the main
function finished, the thread must call destructor and it will call terminate
, and terminate
is abort
here, so you got an exception!
If you uncomment thread.join(), join method returns when the thread execution has completed.
so you cannot get the excepted answer.
Advice:
move
if(t1.joinable())
{
t1.join();
}
and
if(t2.joinable())
{
t2.join();
}
before std::this_thread::sleep_for(std::chrono::milliseconds(5000));
. You can see those three threads exec the same time, but you cannot get the result you want as well, because t1
and t2
sleep 1 second, so the main thread will print the Main waiting...
very quickly. So you should comment the sleep
in t1
and t2
or add the same sleep time to each loop in for
of main.
Hint: Those three thread will compete and the output buffer will be filled randomly, so the output will be unpredictable, you can add a mutex to ensure the output is readable.
Here is my code to reference:
#include <iostream>
#include <thread>
#include <chrono>
#include <mutex>
std::mutex mMutex;
class person {
public:
void startWalking()
{
for(int x = 0; x < 10; x++)
{
mMutex.lock();
std::cout<< "Started Walking.\n";
mMutex.unlock();
//std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
}
};
class car {
public:
void startDriving()
{
for(int x = 0; x< 10; x++)
{
mMutex.lock();
std::cout <<"Started driving.\n";
mMutex.unlock();
//std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
}
};
int main()
{
person p1;
std::thread t1(&person::startWalking, p1);
car c1;
std::thread t2(&car::startDriving, c1);
for(int x = 0; x < 10; x++)
{
mMutex.lock();
std::cout <<"Main waiting...\n";
mMutex.unlock();
//std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
t1.join();
t2.join();
std::this_thread::sleep_for(std::chrono::milliseconds(5000));
return 0;
}
Upvotes: 1