In the first 2 chapters we saw an introduction and different ways to create a thread in C++. In this chapter we shall see ways to attach and detach a thread.
Joining a thread using “join()”.
Why there is a need to call join()?
Once we create a thread, the main program needs to wait till the execution of the thread is completed.
To make main thread wait till the execution of the threads to be completed, we call “join()”.
Simple example:
Below program we have created a thread, and joined it to main thread.
#include <iostream>
#include <thread>
// for more tutorial in C++ visit www.prodevelopertutorial.com
using namespace std;
void myFun(int num)
{
while(num > 0)
{
cout<<num<<endl;
num --;
}
}
int main(void)
{
std::thread t1(myFun, 5);
t1.join();
return 0;
}
Example program to simulate that the program waits at “.join()”
————————————————————
#include <iostream>
#include <thread>
#include <unistd.h> // for usleep
// for more tutorial in C++ visit www.prodevelopertutorial.com
using namespace std;
void myFun(int num)
{
while(num > 0)
{
cout<<num<<endl;
num --;
}
usleep(500000);
}
int main(void)
{
std::thread t1(myFun, 5);
cout<<"Before Join"<<endl;
t1.join();
cout<<"After join"<<endl;
return 0;
}
Output:
Before Join
5
4
3
2
1
After join
If you run the program, the statement “cout<<“After join”<<endl;” will wait for 5 sec, i.e till the execution of the thread is complete then it will be printed.
Calling “.join()” two or more times on the same thread object will result in program termination
Example:
#include <iostream>
#include <thread>
// for more tutorial in C++ visit www.prodevelopertutorial.com
using namespace std;
void myFun(int num)
{
while(num > 0)
{
cout<<num<<endl;
num --;
}
}
int main(void)
{
std::thread t1(myFun, 5);
//calling ".join()" twice
t1.join();
t1.join();
return 0;
}
Output:
terminate called after throwing an instance of 'std::system_error'
what(): Invalid argument
So to prevent a thread to be joined 2 or more times, use “joinable()” function to know if the thread can be joined or not.
joinable() will return true if we need to join the thread, else false if the thread is already joined.
Example:
#include <iostream>
#include <thread>
#include <unistd.h> // for usleep
// for more tutorial in C++ visit www.prodevelopertutorial.com
using namespace std;
void myFun(int num)
{
cout<<num<<endl;
}
int main(void)
{
std::thread t1(myFun, 5);
if (t1.joinable())
{
cout<<"First time joining"<<endl;
t1.join();
}
if (t1.joinable())
{
cout<<"Second time joining, it will not be printed"<<endl;
t1.join();
}
return 0;
}
Output:
First time joining
5
Detach()
We use “detach()” function to detach a thread from parent thread.
Simple example:
In the program below, we have not joined the thread, but we have detached the thread.
#include <iostream>
#include <thread>
#include <unistd.h> // for usleep
// for more tutorial in C++ visit www.prodevelopertutorial.com
using namespace std;
void myFun(int num)
{
cout<<"Start function"<<endl;
usleep(1000000);
cout<<"End function"<<endl;
}
int main(void)
{
std::thread t1(myFun, 5);
cout<<"In main"<<endl;
t1.detach();
cout<<"After main"<<endl;
return 0;
}
Output:
In main
After main
Start function
In the output above, we can see that, the main thread did not wait till the execution of the thread is complete. It quit before it.
Note: Similar to double attach problem, same program termination occurs for double detach() of the thread. Hence, before detaching a thread, check if it is join-able. If the thread is joinable then only we detach the thread.
#include <iostream>
#include <thread>
#include <unistd.h> // for usleep
// for more tutorial in C++ visit www.prodevelopertutorial.com
using namespace std;
void myFun(int num)
{
cout<<"In myFun"<<endl;
}
int main(void)
{
std::thread t1(myFun, 5);
cout<<"In main"<<endl;
t1.join();
if(t1.joinable())
t1.detach();
if(t1.joinable())
t1.detach();
cout<<"After main"<<endl;
return 0;
}