Please help me with a simple question about the output of the following code.
I thought that a thread is executed only when the join() or detach() function is called.
So, I expect the output to print only "pause of 2 seconds ended , ID = 59306", and not to print "pause of 1 seconds ended , ID = 10218" because I thought that only thread 2 would be executed, and thread 1 would NOT be executed. But, I was wrong.
In reality, the output actually prints both of the lines mentioned above, which means both thread 1 and 2 are executed. Is it true ?
Would you please explain to me how the code actually execute both threads ?
==========================
#include <iostream> // std::cout
#include <thread> // std::thread, std::this_thread::sleep_for
#include <chrono> // std::chrono::seconds
void pause_thread(int n)
{
std::this_thread::sleep_for (std::chrono::seconds(n));
std::cout << "pause of " << n << " seconds ended , ID = " << std::this_thread::get_id() << std::endl;
}
int main()
{
std::cout << "Spawning 2 threads...\n";
std::thread t1 (pause_thread,1);
std::thread t2 (pause_thread,2);
std::cout << "Done spawning threads. Now waiting for them to join:\n";
//t1.join();
t2.join();
std::cout << "All threads joined!\n";
return 0;
}
Actual Output :
Spawning 2 threads...
Done spawning threads. Now waiting for them to join:
pause of 1 seconds ended , ID = 10218
pause of 2 seconds ended , ID = 59306
All threads joined!
===================
Update:
Thanks to all comments and answers from everyone.
Now, I understand my incorrect logic because I mistakenly thought that a thread were executed only when the join() or detach() function is called.
Now, I realize that a thread is executed as soon as it is created without the need to call join() or detach(). However, if we call join(), then we can see the output of the thread from the main() function.
CodePudding user response:
Threads start execution not when .join() is called on them, but when they are constructed.
.join() is used to block the calling thread's execution until the thread being joined to has finished execution. It is typically required to join all threads before main() exits for the reason you observed:
When main() reaches the return statement, the scope of the std::thread objects is left. If neither .join() or .detach() has been called on the std::thread managing a thread at this point, the std::thread's destructor is going to call std::terminate() which (by default) aborts the whole program's execution.
Even if you detach the threads instead of joining them, when main() didn't block long enough via calls to .join() and exits before the threads have finished their output, there is a problem. After exiting main(), static storage duration objects are destroyed. One such object is std::cout. When the threads then try to output via std::cout after their wait, it is already destroyed and the program has undefined behavior.
Also note that detaching t1 and joining t2 isn't safe either, although the waiting times seem to suggest that. When exactly threads are scheduled for execution is up to the operating system. It could happen that thread t2 finishes before t1, in which case the issue mentioned above applies again, causing the program to again have undefined behavior.
