Namrata
Namrata

Reputation: 31

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.

Upvotes: 3

Views: 2175

Answers (2)

Zoso
Zoso

Reputation: 3465

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.

Upvotes: 5

hobbs
hobbs

Reputation: 239890

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.

Upvotes: 3

Related Questions