Writing Your First Multithreaded Program in C++

Discussion in 'C++' started by usmanmalik, Jan 24, 2014.

  1. usmanmalik

    usmanmalik New Member

    Joined:
    Dec 28, 2013
    Messages:
    19
    Likes Received:
    14
    Trophy Points:
    0
    Multithreading is one of the most fascinating feature of modern day programming. If you are not familiar with multithreading then most probably you have been writing programs that are single threaded. By single threaded program we mean such a program where program instructions run in a sequence and at one time only single piece of program code is being processed by the processor.

    In the inception stages and computing, single threaded programs were written because hardware need to run multithreaded programs was not available. With the evolvement of hardware technologies and advent of multicore processor, programming style also changed and multithreaded programs were introduced. You would have heard the terms dual core, quad core etc. Core basically refers to part of the processor that can run in parallel with each other. Quad core and dual core systems are often called multiprocessing systems because they are able to process multiple processes at a time.

    Before dwelling into the details of multithreading, some important differences need to be explained here. Multitasking, Multiprocessing and Multithreading, these three terms are often interchangeable used but they are actually different.

    Multitasking

    Multitasking is basically doing multiple computing tasks at a time. Multiprocessing and multithreading are actually types of multitasking.

    Multiprocessing

    A process in operating system is basically a program. Multiprocessing means, running multiple processes on the same machine in parallel. For example, you are viewing this content on your web browser or may be through some other application. At the same time, you might be listening to some songs on some media player application or running some chat application in parallel to the browser. This is called multiprocessing, where multiple programs run in parallel. In the earliest of the computer systems, you could only run single application on your systems.

    Multithreading

    Now coming towards our; Multithreading is fine-grained form of multiprocessing. In multiprocessing, we run multiple programs in parallel; in multithreading we run different pieces of same program in parallel. I often use MS Word example to explain multithreading. You would have noticed that while you are typing on MS Word application, it automatically highlights spelling mistakes while writing and suggests you the corrections. What actually happening is that there are multiple threads running in parallel. One thread is responsible for typing data into your document, one thread is continuously checking spelling and grammar mistakes that you make and one thread is suggesting you possible spellings. There can be other threads running in parallel which are hidden to us. The point here is, that we are running a single MS Word application and different pieces of code of this program are executing in parallel. This is what we call multithreading. A thread is often referred to as the smallest unit that can be executed by processor.

    If you have not been long at it, multithreading is not a simple concept to learn. There are lots of factors that come into play while multithreaded applications are being run, however, luckily enough, our operating system hides those from us and we only have to interact with application programmer’s interface in order to develop multithreaded applications in C++.

    We will see how we can do it, in next section.

    Creating Multithreaded Programs



    Multithreaded programs can be created in various ways. In C and some of the older versions of C++ language, POSIX framework was used for developing multiprogramming applications. However, POSIX fostered, older programming style and its compilation entailed several complex features and functions to be performed. We require a threading framework that allows us to visually write multithreaded code that can be debugged using some IDE like visual studio. . In short we need something like #include <thread> that we can insert on top of our code and sit back and enjoy the built in concurrency features of C++. Some third party vendors have provided such threading libraries that need to be incorporated in the IDE to utilize multithreading functionality. Two of these libraries are boost thread and just threads. Just thread is a commercial thread library and you need to pay for it.

    The C++11 for Multithreading

    We discussed that we need some threading library that can be incorporated in some IDE and is also free. Good news is that Microsoft introduced latest version of C++ programming language called C++11. In this newer version of the C++, several advanced features were introduced. A built in thread class library was also introduced with it. Now you can simply include #include <thread> into your programs and can utilize thread class concurrency features. An important thing to note here is that, C++11 is not available with Visual Studio 2010. You will have to upgrade to Visual Studio 2012 in order to utilize the functionalities of C++11.

    Now let us come to some coding. With the help of a simple example, I will show you how can you create and run a thread in parallel with the main function execution. First look at the code in Example1 and try to understand what is happening there. I will explain it later.

    Note: All the code sample in this article are written in Visual C++11 with Visual studio 2012 as the IDE.
    Code:
    #include <iostream>
    #include <thread>
    //This is the function that will run in parallel
    // It will be passed to the thread
    void thread_method() {
    	std::cout << "Function running in thread "<< std::endl;
    }
    int main() {
    	//This statement will launch thread in parallel to main function
    	std::thread t(thread_method);
    	std::cout << "\nThe main function execution\n";
    	//This is how we join the new thread with main
    	t.join();
    	getchar();
    	return 0;
    }
    Pay attention to the code in Example1. In the beginning of the code we have include the thread library that is shipped with C++11. We will make use of this thread library in our code.

    Next, we have simply created a method called thread_method(). Function is often called method in some of the more advanced languages such as JAVA and C Sharp. Remember, whenever we want to create a new thread that we want to run in parallel, we will define a new function. In other words, if we want a certain piece of code to run in parallel with some other code, we need to place that code in a function. What actually happens is that function is run in a separate thread. Here in Example1, we have defined a function which simply displays that this function is being run in a separate thread parallel to the main function. You must be wondering, how come the main thread runs in a thread. Actually main thread is also running in a thread that compiler creates by default. We don’t need to write code to place main function in a separate thread because in uni-threading applications we don’t need to create thread and one thread is enough for us to achieve our desired functionality.

    Next we have created a thread class using the statement
    Code:
    std::thread t(thread_method);
    It shows that a thread class ‘t’ is created which actually starts a new thread. In this new thread we have passed that function name that we want to execute in parallel. Since we have created a function named thread_method() for this purpose, we will pass this method name to the thread. Note, here we have not passed parameter to the function, we have only passed the name thread_method.

    Join function



    Next we are coming to a very important and crucial concept of thread. The join function of the thread class. Note that in Example1 we have called t.join() on the thread ‘t’. What it actually does is, it says to the parent thread which is main thread in this case that please wait, until I complete my execution.

    std::thread t(thread_method); When this statement executes, a new thread is created which runs the thread_method() function in parallel to the main function. In this case, main function is the parent thread and the thread_method() is running in child thread.

    Since, both the parent and child are running in parallel, therefore a parent can complete its execution before the child function. For instance, it can happen that main function thread completes its execution and program terminates before the child thread is completed. In such cases, child thread will also be terminated. By using join, we prevent this scenario. Join call from the child thread inside the parent thread actually requests the parent to wait until child completes its execution and then terminates.

    You must be thinking, since both main function and thread_method() are now executing in parallel, which of the two display statements in each functions will be displayed first. Before answering this question let us move to our next Example2 where this question will be answered with more concrete explanation. For now, just look at the output of the Example1. If the output is different on your systems, do not worry.

    Output1

    [​IMG]

    In Example1 we only created one thread; therefore we had 2 threads in total. A main function thread and thread_method() function thread. In our next example we will create 10 threads and will pass the same thread_method() to each of the thread and will see the behavior of the execution of these threads. Look at Example2.

    Example2

    Code:
    #include <iostream>
    #include <thread>
    static const int num_of_threads = 10;
    //This is the function that will run in parallel
    // It will be passed to the thread
    void thread_method(int thread_id) {
    	std::cout << "Function running in thread " << thread_id << std::endl;
    }
    int main() {
    	std::thread threads[num_of_threads];
    	//This statement will launch multiple threads in loop
    	for (int i = 0; i < num_of_threads; ++i) {
    		threads[i] = std::thread(thread_method, i);
    	}
    	std::cout << "The main function execution\n";
    	//This is how we join the new thread with main
    	for (int i = 0; i < num_of_threads; ++i) {
    		threads[i].join();
    	}
    	getchar();
    	return 0;
    }
    In this example we have declared a constant variable of type integer. We named it num_of_threads. We declared this variable constant because threads can only take constant variables as their parameter. Next, we created an array of threads using the statement
    Code:
    std::thread threads[num_of_threads];
    Since we initialized the num_of_threads variable to 10, this array will be able to hold 10 threads. After that we have initialized ten instances of thread class inside the for loop and every time we have passed a variable ‘i’ with the name of the method that we want to run in the thread which is thread_method() in this case. Note, here again we have not mentioned the parameter bracket with the method name, we only passed thread_method. After the method name we have passed another argument which should match the first argument of the function declaration. For instance, the first argument that thread_method() function accepts is an integer type variable, therefore in thread declaration the second argument should be of type integer and so on. If thread_method() had second argument of type char, we will have to pass third argument of type char in thread creation call. The first argument in thread creation call will always be the name of the function which we want to execute in parallel.

    As the loop executes, the memory address of each created thread will be stored in the thread array using this line
    Code:
    threads[i] = std::thread(thread_method, i);
    Next, we have displayed the statement in main function "The main function execution”.

    Now we have ten threads and we will have to call join on each of these threads, therefore we have again executed a for loop and have traversed the thread array. We then executed join on each of the threads in the thread array using this line
    Code:
    threads[i].join();
    This way we will have elven threads being executed in parallel: One will be our main function thread and the other ten threads are the ones which we have created. Now, we are going to answer the question that which thread will execute faster since, all the eleven threads are running in parallel. The answer is that all these programs will try access the CPU cycles at the same time. A race condition occurs between these threads. The thread that accesses the CPU cycles first will be executed first. It is totally random. Therefore if you run the code multiple times, you will get different outputs most of the time. Because during first execution, thread 2 might access the CPU cycles before thread 0 and 1 and so on. It can be seen in the output that though we created thread 2 earlier than thread 3, 5 and 7 but they are executed first because CPU cycles were allotted to them first. Again this execution pattern is purely random and can be optimized using some synchronization mechanism which is beyond the scope of this article.

    Output2

    [​IMG]
     
    Last edited by a moderator: Jan 21, 2017
    1 person likes this.

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice