C++ multithreading library<thread>

C++11 introduced multithreading support, through<thread>the library, developers can easily implement parallel processing in programs.

This article will introduce<thread>The basic concepts, definitions, syntax of the library, and how to use it to create and manage threads.

A thread is the smallest unit of program execution and the smallest unit that the operating system can schedule for computation.

In multithreaded programs, multiple threads can execute in parallel, improving program execution efficiency.

C++ <thread>Library Overview

<thread>The library is part of the C++ standard library, providing the basic functionality for creating and managing threads. It includes the following key components:

  • std::thread: Represents a thread; it can create, start, wait for, and destroy threads.
  • std::this_thread: Provides some static member functions for operating on the current thread.
  • std::thread::id: The unique identifier of the thread.

Creating Threads

To create a thread, you need to instantiatestd::threadclass, and pass a callable object (function, lambda expression, or member function of an object) as an argument.

Example

#include <iostream>
#include <thread>

void print_id(int id) {
    std::cout << "ID: " << id << ", Thread ID: " << std::this_thread::get_id() << std::endl;
}

int main() {
    std::thread t1(print_id, 1);
    std::thread t2(print_id, 2);
}

Starting Threads

Createstd::threadAfter the object, the thread will immediately start executing; you can calljoin()method to wait for the thread to complete.

t1.join();
t2.join();

Wait for the thread to complete

join()method will block the current thread until the called thread completes execution.

Destroying Threads

When the thread has finished executing, you can usedetach()method to detach the thread, or letstd::threadthe object go out of scope and be destroyed automatically.

t1.detach(); // 线程将继续运行,但无法再被 join or  detach

Example: Using<thread>Create parallel computing

Below is an example using<thread>Example of parallel computing implemented with the library, calculating the sum of two numbers.

Example

#include <iostream>
#include <thread>

int sum = 0;

void add(int a, int b) {
    sum += a + b;
}

int main() {
    int a = 5;
    int b = 10;

    std::thread t1(add, a, b);
    std::thread t2(add, a, b);

    t1.join();
    t2.join();

    std::cout << "Sum: " << sum << std::endl; // Output result: Sum: 30
}

The output result is:

Sum: 30

In the following example, we will create two threads, each of which executes a simple function that prints a message and sleeps for a while:

Example

#include <iostream>
#include <thread>
#include <chrono>

// Simple function, executed in a thread
void print_message(const std::string& message, int delay) {
    std::this_thread::sleep_for(std::chrono::milliseconds(delay));
    std::cout << message << std::endl;
}

int main() {
    // Create two threads and execute the print_message function
    std::thread t1(print_message, "Hello from thread 1", 1000);
    std::thread t2(print_message, "Hello from thread 2", 500);

    // Wait for thread t1 to finish
    if (t1.joinable()) {
        t1.join();
    }

    // Wait for thread t2 to finish
    if (t2.joinable()) {
        t2.join();
    }

    std::cout << "Main thread finished." << std::endl;

    return 0;
}

The output result is:

Hello from thread 2
Hello from thread 1
Main thread finished.

Notes

  • Thread safety: In a multithreaded environment, shared resources require synchronized access to avoid data races.
  • Thread lifecycle: Ensure that the thread object is correctly handled after the thread completes execution to avoid resource leaks.

Classes and functions

<thread>The library contains a series of classes and functions for creating, managing, and synchronizing threads.

The following is about C++<thread>Detailed introduction to the library:

Main components

  • std::thread
  • std::mutex
  • std::lock_guard
  • std::unique_lock
  • std::condition_variable
  • std::future and std::promise
  • std::async

std::thread

The std::thread class is used to create and manage threads.

Example

#include <iostream>
#include <thread>

void print_hello() {
    std::cout << "Hello from thread!" << std::endl;
}

int main() {
    std::thread t(print_hello);
    t.join(); // Wait for thread t to finish
    return 0;
}

Important methods

  • join(): Wait for the thread to end.
  • detach(): Put the thread in the background and no longer wait for it to end.
  • joinable(): Check whether the thread can be joined or detached.

std::mutex

The std::mutex class is used to synchronize access to shared resources.

Example

#include <iostream>
#include <thread>
#include <mutex>

std::mutex mtx; // Create a global mutex object
int shared_resource = 0; // Shared resource

// Thread function
void increment() {
    std::lock_guard<std::mutex> lock(mtx); // Lock to ensure thread safety
    ++shared_resource;
    std::cout << "Incremented shared_resource to " << shared_resource << std::endl;
    // lock is automatically released when lock_guard leaves scope
}

int main() {
    std::thread t1(increment);
    std::thread t2(increment);
   
    t1.join(); // Wait for thread t1 to finish
    t2.join(); // Wait for thread t2 to finish

    std::cout << "Final value of shared_resource: " << shared_resource << std::endl;

    return 0;
}

std::lock_guard

std::lock_guard is an RAII-style lock manager used to automatically manage the lock's lifecycle.

Example

#include <iostream>
#include <thread>
#include <mutex>

std::mutex mtx;

void print_thread_id(int id) {
    std::lock_guard<std::mutex> lock(mtx);
    std::cout << "Thread ID: " << id << std::endl;
}

int main() {
    std::thread t1(print_thread_id, 1);
    std::thread t2(print_thread_id, 2);
    t1.join();
    t2.join();
    return 0;
}

std::unique_lock

std::unique_lock provides more flexible lock management than std::lock_guard.

Example

#include <iostream>
#include <thread>
#include <mutex>

std::mutex mtx;

void print_thread_id(int id) {
    std::unique_lock<std::mutex> lock(mtx);
    std::cout << "Thread ID: " << id << std::endl;
    lock.unlock(); // Can be manually unlocked
    // ... other operations
}

int main() {
    std::thread t1(print_thread_id, 1);
    std::thread t2(print_thread_id, 2);
    t1.join();
    t2.join();
    return 0;
}

std::condition_variable

std::condition_variable is used for waiting and notification between threads.

Example

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>

std::mutex mtx;
std::condition_variable cv;
bool ready = false;

void print_id(int id) {
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, []{ return ready; });
    std::cout << "Thread ID: " << id << std::endl;
}

void set_ready() {
    std::unique_lock<std::mutex> lock(mtx);
    ready = true;
    cv.notify_all();
}

int main() {
    std::thread t1(print_id, 1);
    std::thread t2(print_id, 2);
   
    std::this_thread::sleep_for(std::chrono::seconds(1));
    set_ready();
   
    t1.join();
    t2.join();
    return 0;
}

std::future and std::promise

std::future and std::promise are used to pass results between threads.

Example

#include <iostream>
#include <thread>
#include <future>

void calculate_square(std::promise<int> && p, int x) {
    p.set_value(x * x);
}

int main() {
    std::promise<int> p;
    std::future<int> f = p.get_future();
   
    std::thread t(calculate_square, std::move(p), 5);
   
    std::cout << "Square: " << f.get() << std::endl;
   
    t.join();
    return 0;
}

std::async

std::async is used to start asynchronous tasks and returns a std::future.

Example

#include <iostream>
#include <future>

int calculate_square(int x) {
    return x * x;
}

int main() {
    std::future<int> result = std::async(calculate_square, 5);
   
    std::cout << "Square: " << result.get() << std::endl;
   
    return 0;
}

C++'s<thread>The library provides developers with powerful multithreading support. Through the introduction in this article, we should be able to understand the basic concepts of threads and learn how to use<thread>the library to create and manage threads. In actual development, reasonable use of multithreading can significantly improve program performance and responsiveness.

other extensions