C++ Threads and Join
A thread is a separate line of work that runs alongside the main program. The main program starts a thread with std::thread and waits for it with join.
One thread stores a value
The compute function adds two numbers and stores the result through a pointer. Main joins the thread and only then prints the stored value.
#include <iostream>
#include <thread>
void compute(int* result) {
*result = 17 + 25;
}
int main() {
int result = 0;
std::thread worker(compute, &result);
worker.join();
std::cout << "Result: " << result << std::endl;
return 0;
}Three threads fill separate slots
Each thread writes one slot of the array and no slot is shared. Main joins all three threads before it prints the slots and their sum.
#include <array>
#include <iostream>
#include <thread>
void fillSlot(std::array<int, 3>* slots, int index, int value) {
(*slots)[index] = value;
}
int main() {
std::array<int, 3> slots = {0, 0, 0};
std::thread first(fillSlot, &slots, 0, 10);
std::thread second(fillSlot, &slots, 1, 20);
std::thread third(fillSlot, &slots, 2, 30);
first.join();
second.join();
third.join();
int sum = slots[0] + slots[1] + slots[2];
std::cout << "Slots: " << slots[0] << " " << slots[1] << " " << slots[2] << std::endl;
std::cout << "Sum: " << sum << std::endl;
return 0;
}A thread takes an argument
The thread receives a name as an argument and builds a greeting from it. Main prints the greeting after the join.
#include <iostream>
#include <string>
#include <thread>
void buildGreeting(std::string name, std::string* greeting) {
*greeting = "Hello, " + name;
}
int main() {
std::string greeting = "";
std::thread worker(buildGreeting, std::string("Mina"), &greeting);
worker.join();
std::cout << greeting << std::endl;
return 0;
}Example
#include <array>
#include <iostream>
#include <thread>
void squareInto(int value, int index, std::array<int, 4>* slots) {
(*slots)[index] = value * value;
}
int main() {
std::array<int, 4> slots = {0, 0, 0, 0};
std::thread first(squareInto, 3, 0, &slots);
std::thread second(squareInto, 5, 1, &slots);
std::thread third(squareInto, 7, 2, &slots);
std::thread fourth(squareInto, 9, 3, &slots);
first.join();
second.join();
third.join();
fourth.join();
int total = slots[0] + slots[1] + slots[2] + slots[3];
std::cout << "Squares: " << slots[0] << " " << slots[1] << " " << slots[2] << " " << slots[3] << std::endl;
std::cout << "Total: " << total << std::endl;
return 0;
}Key points
- std::thread starts a new line of work when the thread object is made.
- Use join to wait until a thread has finished its work.
- A value stored by a thread is safe to read after join returns.
- Each thread in these programs writes only to its own storage.
- The main program reads results only after every thread has joined.
In this example, four threads each square one number into a separate slot. Main joins all four threads before reading any slot. The printed squares are 9, 25, 49, and 81, and their total is 164.
Note
A thread that is never joined stops the program when its object is destroyed.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
Why does main call join before printing a value a thread stored?