Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What thread.join() do in multithreading?

I am trying to understand the thread join in C / C++. And I get to know that

std::thread::join() function makes the current thread wait until the thread identified by *this has finished executing.

But I can't understand why the positioning of the join function is important and why this two code works differently.

code 1:

#include <iostream>
#include <thread>
#include<vector>
#include <unistd.h>

using namespace std;

void func(int x)
{
  sleep(100);
  cout<<x<<endl;
}

int main() {
  
  vector<thread> a;

  for(int i=0;i<10;i++)
  {
    a.emplace_back(func,i);
  }

  for (auto &thr : a) {
      thr.join();
      cout<<"next"<<endl;
  }

  cout<<"finish"<<endl;
}

Output:

01
3

next
9
7
45
6
8
2next


next
next
next
next
next
next
next
next
finish

Code 2:

#include <iostream>
#include <thread>
#include<vector>
#include <unistd.h>

using namespace std;

void func(int x)
{
  sleep(100);
  cout<<x<<endl;
}

int main() {
  
  vector<thread> a;

  for(int i=0;i<10;i++)
  {
    a.emplace_back(func,i);
    a.back().join();
    cout<<"next"<<endl;
  }

  cout<<"finish"<<endl;
}

Output:

0
next
1
next
2
next
3
next
4
next
5
next
6
next
7
next
8
next
9
next
finish

At first I thought that in code 1 as I join the threads later maybe they executed and finished already, but increasing the sleep time giving same result. So, I am confused.

like image 551
Namrata Avatar asked Jun 27 '26 21:06

Namrata


2 Answers

In your first version of code, this block

  for(int i=0;i<10;i++)
  {
    a.emplace_back(func,i);
  }

Does 2 things, it creates a std::thread instance and launches the threads. Now these threads are allowed to run until the main thread calls join()on them as in the next piece of code,

  for (auto &thr : a) {
      thr.join();
      cout<<"next"<<endl;
  }

So you,

  1. Create all threads
  2. Let all of them run
  3. Call join() on them one by one.

In your Version 2, you again create the thread but then immediately call join() on the last inserted thread via back() i.e. the thread just created.

  for(int i=0;i<10;i++)
  {
    a.emplace_back(func,i);
    a.back().join();
    cout<<"next"<<endl;
  }

Thus each of the threads is launched, runs to its completion, and is then called join() upon. You essentially serialize the threads, hence the output. So here you,

  1. Create a single thread
  2. Allow it to run
  3. Call join() on it.
  4. Repeat this for all threads.
like image 125
Zoso Avatar answered Jun 29 '26 09:06

Zoso


In the first snippet, you start all the threads, then wait for all of them. In the second snippet, you wait for a thread to complete right after you start it, before moving on to the next one, so only one is running at a time.

like image 38
hobbs Avatar answered Jun 29 '26 11:06

hobbs



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!