User:Eric B. and Rakim/Threads (computer science)

From Wikipedia, the free encyclopedia

A thread is a line of execution for a program. Simple programs only have one line of execution and are therefore sometimes called single-threaded. This is an example of that kind of program in C:

       #include <stdio.h>
       
       int main()
       {
               int n;
               for (n = 0; n < 10; n++)
               {
                       printf("n is %d.\n", n);
               }
       }

Single-threaded programs are relatively easy to understand. They only do one thing at once and therefore only has one state at any time. The output of the program will be:

       n is 0.
       n is 1.
       ...
       n is 9.

When the computer executes the program, it executes all the instructions in the order they were typed. First it makes the variable n, sets it to 0, checks if it is less than 3, prints "n is 0.", adds 1 to n, checks if it is less than 3, prints "n is 1.", etc.

If a program has more than one thread it is called multi-threaded, and when it is executed it will do more than one thing simultaneously. Here is an example of a multi-threaded program written in C with pthreads:

       #include <stdio.h>
       #include <pthread.h>
       #include <unistd.h>
       
       /* First thread. Prints even numbers: 0, 2, 4, 6, 8
       void print_even()
       {
               int n;
               for (n = 0; n < 5; n++)
               {
                       printf("n is %d.\n", n * 2);
                       sleep(1);
               }
       }
       
       /* Second thread. Prints odd numbers: 1, 3, 5, 7, 9
       void print_odd()
       {
               int n;
               for (n = 0; n < 5; n++)
               {
                       printf("n is %d.\n", n * 2 + 1);
                       sleep(1);
               }
       }
       
       /* Main function. */
       int main()
       {
               pthread_t thread1, thread2;
               
               /* Create and start the threads. */
               pthread_create(&thread1, NULL, (void *)print_even, NULL);
               pthread_create(&thread2, NULL, (void *)print_odd, NULL);
               /* Wait for the threads to finish. */
               pthread_join(thread1, NULL);
               pthread_join(thread2, NULL);
       }

To compile this program, you need to link with pthread. With gcc it is done like this:

       gcc -o program program.c -lpthread
Output of the two threads.
Output of the two threads.

The output of the program will be identical to the previous program. However, experiment with the parameters to the calls to the sleep function and seemlingly strange things will happen. As will become apparent is that the order of the output, is totally dependant on what parameters the sleep calls receive. If the threads was run one by one, the output would look like the illustration on the right. But when they are run in parallell, we can't on beforehand predict what the exact output will be.

How threads are useful[edit]

Threads are useful in any situation when a program needs to do two things, tasks, at once. Especially when one of the tasks involves waiting for input from a resource, like the user. A common use of threads is having one thread paying attention to the graphical user interface, while others do a long calculation in the background. The following pseudo-code demonstrates how one might solve the problem employing threads.

       void interactWithUser()
       {
               while(1)
               {
                       waitUntilTheUserDoesSomething();
                       doWhatTheUserWants();
               }
       }
       
       void longCalculation()
       {
               calculateOneTrillionDecimalsOfPi();
       }
       
       void main()
       {
               /* In here would be code that starts the both threads and
               waits until the user wants to quit the application. */
       }

The problem IS possible to solve with a single-threaded approach. It would look something like this, but would be much worse:

       void main()
       {
               while(userDoesntWantToQuit)
               {
                       if (hasUserDoneSomething())
                               doWhatTheUserWants();
                       calculateOnePartOfTheProblem();
               }
       }

The reason that this approach is that we have to use polling and that we have to switch between serving the user and working on our problem. Polling means that we periodically check if some event has happened and that is exactly what the line if (hasUserDoneSomething()) does. We also have to break our calculation of pi down in small manageable chunks that doesn't take so long to calculate, otherwise we won't have time to serve the user. That is what calculateOnePartOfTheProblem() call does.

As a result, the multi-threaded program can respond to user's interaction much faster than a single-threaded approach. Also, when the user isn't doing something, the computer can devote all its resources to calculate the long calculation. The last and most important advantage is that it will be much easier to read and write the source with threads.

Threading issues[edit]

Previously it was said that threads can make a program easier to write. However, there are so many more things that can go wrong when using multiple threads. In fact, the pitfalls are so many that many consider threads the most complicated part of Computer Science.