Codementor Events

Thread: How can I create a thread?

Published Mar 20, 2020

Source File is here.

Hey welcome folks.

C++11 provides a threading support. Before this we had to use pthread of C lang.

C++ threading lib is defined in <thread> header file.

Thread can be created by multiple ways :

Thread with Function Pointer
Thread with Function Object
Thread with Lambda
Thread with Member Function

Here we will discuss creation of thread using Function pointer.

Suppose we have a fun1()

int fun1( const string str){
          cout << str << endl;
}

You can launch multiple threads using std::thread.

std::thread t1(fun1);

Constructor of a thread class is a variadic template, which means that it accepts any number of arguments. We will see how to pass arguments and how not to pass arguments to a C++ thread in next article.

Once we created a thread, we need to join newly created thread to main() thread. If we fail to call join() main thread will not wait for the completion of our newly created thread. To make sure that main thread keeps running until our thread(s) are completed.

t1.join();

If we have 2 or more than 2 threads accessing a shared resource. There are high chances of Race Condition between threads. There are multiple ways to synchronize threads. One of those which C++ provides is Mutex, we will discuss this.

Lets say we have a globe shared variable, which will be shared between all threads.

int shared;

For this example we will print even numbers in one thread and odd numbers in other.
We will have to include mutex header in order to use std::mutex.

#include > <mutex>

Now lets create a global std::mutex object.

mutex mutObj;

Now lets add some code to fun1(). This thread will print all the even numbers between 0 to 10.

int fun1(){
    //std::this_thread::sleep_for(std::chrono::seconds(2));
    for(;shared < 10;){
        if(0== (shared%2)){
            mutObj.lock();
            shared++;
            cout<< std::this_thread::get_id() <<" fun1(): "<< shared<<endl;
            mutObj.unlock();
        }
    }
}

Lets add one more function fun2() which will print odd numbers.

int fun2(){
    //std::this_thread::sleep_for(std::chrono::seconds(2));
    for(;shared < 10;){
        if(0!= (shared%2)){
            mutObj.lock();
            shared++;
            cout<< std::this_thread::get_id() <<" fun2(): "<< shared<<endl;
            mutObj.unlock();
        }
    }
}

In both functions fun1() and fun2(), we are running a for loop with only terminating condition, we can also use while(). But I like for loop, so I am using here.

In this loop we have a if condition to check even or odd number.

Now here comes the synchronization technique, use of mutex object. Because ‘shared’ is accessed in both the function and incremented.

Shared++;

So before increment ‘shared’ we will call std::mutex::lock() function of std::mutex class using ‘mutObj’

mutObj.lock();

Now once shared is incremented, lets call std::mutex::unlock() which will release the lock.

mutObj.unlock();

How this will work?

A thread that wants to use memory shared with other threads tries to lock a mutex object. If another thread is currently holding this lock, the new thread that wants to to gain access blocks until the lock is released, or until timeout interval is expires. Once lock is released new thread will acquire the lock.

If more than 2 threads are waiting for lock, there are no guarantees as to which thread is granted the lock and thus allowed to proceed.

Next we will see how to pass arguments to a thread. More importantly how not to.

See You in next article.
For more interesting articles and information, please check
www.jhadheeraj.com/blog or click on my picture at right bottom and schedule a 1:1 session.

Discover and read more posts from Dheeraj Jha
get started
post commentsBe the first to share your opinion
Show more replies