Reputation: 610
I've been learning more about multithreading and locking, which has led me to the basic example provided by http://www.cplusplus.com/reference/thread/thread/join/
The basic explanation provided by that page is:
The function returns when the thread execution has completed.
Okay, so it kind of sounds like we start a thread, and we will resume the calling thread when the thread we started completes.
Here is some example code from the site, that I've added a print statement to.
#include <iostream>
#include <thread>
#include <mutex>
#include <unistd.h>
std::mutex mtx;
void print_block (int n, char c) {
mtx.lock();
for (int i = 0; i < n; i++)
{
std::cout << c;
}
std::cout << std::endl ;
mtx.unlock();
return;
}
int main()
{
std::thread th1(print_block, 50, '*');
std::thread th2(print_block, 60, '$');
th1.join();
//my print statement
std::cout << "In between thread joins" << std::endl;
th2.join();
return 0;
}
Based on the description of join I see, I would expect the output to be:
**************************************************
In between thread joins
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
My logic is:
Main thread calls th1.join, so main thread halts execution until th1.join completes.
th1 execution completes after printing out stars, and then my print statement executes
th2 execution begins and ends
In reality this isn't the case, th2 can execute before th1, my print statement usually comes out last. What does join actually do to the main thread? It doesn't seem to actually block it like I keep reading online.
Regardless, my interpretation makes no sense as it seems like it would be the same as a single threaded process. Help!
TLDR;
What really happens when you call join? The new thread begins, but what happens to the main thread? If the main thread does block, why isn't my example the case?
Thanks
EDIT:
I think I understand. For some reason I thought that th1 begins executing when join is called. th1 begins executing when the constructor is called. Join will block the main thread until th1 is finished after it begins executing. Thanks everyone!
Upvotes: 0
Views: 180
Reputation: 21576
That example is bad (reasons below);
What really happens when you call join? The new thread begins, but what happens to the main thread? If the main thread does block, why isn't my example the case?
th1.join()
will block execution of the current thread(in this case the thread of execution in which the function main()
is running) until the thread of execution represented by th1
completes and returns.
Now, this is irrespective of whether th2
completes before th1
- (there's no guarantee that thread th1
enters the function and picks the lock before the thread th2
). All that method is saying is, "do not continue until th1
is completed".
So, yes, th2
may finish before th1
, but
std::cout << "In between thread joins" << std::endl;
will never be executed until th1
finishes.
Bad example:
std::lock_guard
. And please prefer using cppreference.com henceforth.std::cout ...
in your int main()
isn't protected, yes, std::cout
is free from race, but not free from interleaving the character output when used by multiple threadsstd::thread
is probably not what you want to use. And also, prefer higher abstractions such as std::async
.std::cout ...
in your int main()
is assumed to be an indivisible transaction, putting th1.join()
before it and th2.join()
after it is just a deceitful. I would have the joins follow each other on code.Upvotes: 2