How to Create Threads in C++11 / C++14? | Multithreading – Part 1

In this lecture, we will learn how to create threads in C++ using std::thread.

Introduction to the C++11 Thread Library

The original C++ Standard supported only single-threaded programming. However, the new C++ Standard, often referred to as C++11 or C++0x, was published in 2011. With C++11, a new thread library was introduced.

Compilers Required:
Linux: gcc 4.8.1 (with full concurrency support)
Windows: Visual Studio 2012 and MingW

**How to Compile on Linux: **

g++ --std=c++11 sample.cpp -lpthread

Thread Creation in C++11

Every C++ application has one default main thread, which is the main() function. With C++11, we can create additional threads by instantiating objects of the std::thread class. Each std::thread object can be associated with a separate thread.

Required Header:

#include <thread>

std::thread Constructor in C++11

The std::thread constructor in C++11 allows for the association of a callback with the thread object. This callback is then executed upon the start of the new thread. The valid callbacks include:

  1. Normal Function
  2. Function Objects (Functors)
  3. Lambda Functions

You can create a thread object as follows:

std::thread thObj(<CALLBACK>);

Once the thread object is instantiated, the new thread begins execution immediately, running the provided callback in parallel to the thread that initiated it. Furthermore, one thread can opt to wait for another to finish by invoking the join() method on the latter’s thread object.

Every program has a main function, we will refer to that as main Thread.

Let’s delve into an illustrative scenario: The main thread spawns a new thread. Subsequent to this action, the main thread outputs some data to the console, then waits for the completion of the newly minted thread.

Now, let’s implement the above using the three a forementioned callback mechanisms.

Creating a thread using Normal Function

To create a thread using a function pointer, first of all, we need to include the <thread> header file.

We will create a normal function that returns void and also does not accept any parameters. Like this,

void thread_function()
{
    for (int i = 0; i < 5; i++)
    {
        std::cout << "thread function Executing" << std::endl;
    }
}

Now, if we want to execute this function as a separate thread from the main thread, we will create a thread object and pass this function as a parameter into the constructor.

// Create a Thread object
std::thread threadObj(thread_function);

As soon as we create the thread object, the thread will start parallelly to the main function. In this thread, it will execute the given function. After creating the thread object, as the thread has already started, we can continue doing other tasks in the main function. When we are done with the tasks in the main function, we can call the join() function on the thread object. This function will wait until the thread finishes. If the thread is already finished, then it will return immediately.

for (int i = 0; i < 5; i++)
{
    std::cout << "Display From MainThread" << std::endl;
}    

// Wait for the thread to finish
threadObj.join();

So, the join() function basically waits for the thread to finish before continuing. Alternatively, if you don’t want to wait for the thread and just want to continue, you can call the detach() function. In this example, we will call the join() function and wait for the thread to finish. The complete example is as follows,

#include <iostream>
#include <thread>

// A function that will ptint a line on console 5 times
void thread_function()
{
    for (int i = 0; i < 5; i++)
    {
        std::cout << "thread function Executing" << std::endl;
    }
}

int main()
{
    // Create a Thread object
    std::thread threadObj(thread_function);

    for (int i = 0; i < 5; i++)
    {
        std::cout << "Display From MainThread" << std::endl;
    }    

    // Wait for the thread to finish
    threadObj.join();

    std::cout << "Exit of Main function" << std::endl;
    return 0;
}

Output:

Display From MainThread
Display From MainThread
Display From MainThread
Display From MainThread
Display From MainThread
thread function Executing
thread function Executing
thread function Executing
thread function Executing
thread function Executing
Exit of Main function

In this example, the function is executed on a separate thread from the main thread, and then we called the join() function.

Creating a thread using Function Objects

To create a thread using a function object, we pass the function object as an argument to the std::thread class constructor. For instance, consider the following function object where we have overloaded the operator():

class SomeFunctor
{
    public:

        void operator()()
        {
            for (int i = 0; i < 5; i++)
            {
                std::cout << "Display Thread Executing" << std::endl;
            }
        }
};

In this function object, we run a loop to print a message to the console five times. When instantiating the std::thread object, we can pass this function object as an argument:

// Create a Thread
std::thread threadObj((SomeFunctor()));

Upon the thread object’s creation, the new thread starts executing immediately. Subsequent to this, we can proceed with other operations in the main function. Once we’ve finished executing our main thread’s tasks, we can use the join() method on the thread object. This ensures that the main thread waits for the newly spawned thread to complete before proceeding.

Let’s see the complete example:

#include <iostream>
#include <thread>

// Afunction Object
class SomeFunctor
{
    public:

        void operator()()
        {
            for (int i = 0; i < 5; i++)
            {
                std::cout << "Display Thread Executing" << std::endl;
            }
        }
};

int main()
{
    // Create a Thread using Function Object
    std::thread threadObj((SomeFunctor()));

    for (int i = 0; i < 5; i++)
    {
        std::cout << "Display From Main Thread " << std::endl;
    }

    std::cout << "Waiting For Thread to complete" << std::endl;

    // Wait for the thread to finish
    threadObj.join();

    std::cout << "Exiting from Main Thread" << std::endl;
    return 0;
}

Output:

Display From Main Thread 
Display From Main Thread 
Display Thread Executing
Display Thread Executing
Display From Main Thread 
Display From Main Thread 
Display From Main Thread
Waiting For Thread to complete
Display Thread Executing
Display Thread Executing
Display Thread Executing
Exiting from Main Thread

Creating a thread using Lambda functions

We can also instantiate a thread object using a lambda function. For this purpose, we provide a lambda function that neither accepts parameters nor returns a value. Inside this lambda, we’ll include logic to print a message to the console five times. Here’s an example:

// Create a Thread from Lambda function
std::thread threadObj([]() {
    for(int i = 0; i < 5; ++i) {
        std::cout << "Display Thread Executing" << std::endl;
    }
});

Upon creating the std::thread object with the lambda as its argument, the new thread starts executing. Concurrently, the main thread can carry out its tasks. Once the main thread completes its operations, the join() method can be invoked on the thread object. This ensures that the main thread waits for the lambda thread to complete its execution. Following this, the main function can gracefully terminate.

Let’s see the complete example:

#include <iostream>
#include <thread>

int main()
{
    // Create a Thread from Lambda function
    std::thread threadObj([]() {
        for(int i = 0; i < 5; ++i) {
            std::cout << "Display Thread Executing" << std::endl;
        }
    });

    for (int i = 0; i < 5; i++)
        std::cout << "Display From Main Thread" << std::endl;

    // Wait for the thread to finish
    threadObj.join();

    std::cout << "Exiting from Main Thread" << std::endl;
    return 0;
}

Output:

Display From Main Thread 
Display From Main Thread 
Display Thread Executing
Display Thread Executing
Display From Main Thread 
Display From Main Thread 
Display From Main Thread
Waiting For Thread to complete
Display Thread Executing
Display Thread Executing
Display Thread Executing
Exiting from Main Thread

Differentiating between threads using Thread ID

Every thread in C++ has an associated unique ID. This ID can be fetched using the get_id() member function provided by the std::thread class. If you’re inside a function executed by a thread and wish to retrieve its ID, you can invoke std::this_thread::get_id(). This will return the ID of the currently executing thread.

Member function, gives id of associated thread object i.e.

std::thread::get_id()

To get the identifier for the current thread use,

std::this_thread::get_id()

However, if get_id() is called on a thread object that hasn’t started any thread execution (or has already finished its operation), it will return a default-constructed std::thread::id object. The ID returned by get_id() is of type std::thread::id and can be used for comparison operations or printed to the console.

Let’s illustrate this with an example. We’ll create two threads using the same function. Inside the function, we’ll print the ID of each thread. After the threads finish executing, we’ll compare their IDs and then join them. By doing this, we can distinguish between threads or identify a particular thread using its ID.

#include <iostream>
#include <thread>

void thread_function()
{
    std::cout<<"Inside Thread :: ID  = "<<std::this_thread::get_id()<<std::endl;    
}

int main()  
{
    // Create two thread objects
    std::thread threadObj1(thread_function);
    std::thread threadObj2(thread_function);

    // Compare the Tead Id of two threads
    if(threadObj1.get_id() != threadObj2.get_id())
    {
        std::cout<<"Both Threads have different IDs"<<std::endl;
    }


    std::cout<<"From Main Thread :: ID of Thread 1 = "<<threadObj1.get_id()<<std::endl;    
    std::cout<<"From Main Thread :: ID of Thread 2 = "<<threadObj2.get_id()<<std::endl;    

    // Wait for both the thread to finish
    threadObj1.join();    
    threadObj2.join();    
    return 0;
}

Output:

Both Threads have different IDs
From Main Thread :: ID of Thread 1 = 139743744489024
From Main Thread :: ID of Thread 2 = 139743736096320
Inside Thread :: ID  = 139743736096320
Inside Thread :: ID  = 139743744489024

So this is how we can fetch the Thread ID of each Thread in C++.

Summary

In this article, we explored three distinct methods to create a thread in C++11 and C++14. Additionally, we discussed the concept of thread IDs.

2 thoughts on “How to Create Threads in C++11 / C++14? | Multithreading – Part 1”

  1. Pingback: C++11 Multithreading – Part 2: Joining and Detaching Threads – thisPointer.com

  2. Pingback: RAII wrapper class for C++11 std::thread – Yet another programmer blog

Comments are closed.

Scroll to Top