Multi Thread Programming
Multi Thread Programming
Table of Contents
Table of Contents.2
Index of Figures and Listings.2
Introduction to Threads and Multithreading........3
What are Threads?..3
The Benefits of Multithreading..3
Drawbacks of Multithreading.4
Classes of Multithreading5
Cooperative versus Preemptive Multithreading.5
Multithreading in Windows NT..6
Background.6
Threads and the Microsoft Win32 API..7
Programming Example 1..10
Threads and the C Run-Time Library...11
Programming Example 2..12
Conclusion14
Works Cited.14
Drawbacks of Multithreading
While the use of multiple threads can increase the flexibility and
parallelism over a single thread, it also adds a certain amount of overhead in the
form of additional scheduling and context switching(Marrin 78). For
multithreading to be beneficial, the run time of each individual thread must be
long compared to the time it would take to switch between them.
Classes of Multithreading
Cooperative versus Preemptive
Multithreading in Windows NT
Background
one thread before it can execute, so even switching between processes means
switching between threads.
The objective of coding a multithreaded program is to make each thread
think it runs exclusively, while in reality this is not the case. As mentioned
earlier, each thread has its own context record. To a thread, the context record is
the data it has to preserve to resume execution in the same state it was in before
losing control over the CPU. In Windows NT, the context of a thread consists of
a client identification number, two stacks, the state of the processor, and its own
private data. However, Windows NT handles context switching such that the
threads dont need to know what state they are in, from a programmers
perspective.
adding in the background. Also, some details like parameters to the functions that
handle file I/O have been omitted to keep the focus on threads.
If the Win32 API is used to implement multithreading, the actual threads
are created with a call to CreateThread. To get a better feel for exactly what
Windows NT needs to create a thread, you can look at the six parameters used in
this call. The first parameter is a pointer to a SECURITY_ATTRIBUTES
structure, which contains a security descriptor (to control sharing of the thread
between other processes). A value of NULL means no security is needed. The
second parameter to CreateThread is a stack size, which is necessary because each
thread runs on its own stack. Passing a value of zero here tells Windows NT to
make the stack the same size as that of the threads process stack. The third
parameter is the address of the thread function, where execution will begin, and
the fourth argument is the thread function parameters. CreateThread expects the
thread function to be of type WINAPI. Fifth is an integer that can be either a
zero, where the thread will run as soon as it is created, or
CREATE_SUSPENDED, where the thread will be created, but will not run unless
it is resumed with a call to ResumeThread. The last parameter is the thread ID.
Using listing 1 as an example, notice that the thread is created with no security
attributes, the same stack size as its process, a pointer to the thread function with
no arguments, and will run immediately upon being created. After the thread has
been created, and the code for the thread has finished executing, the thread needs
to be closed, which is done in Windows NT with a call to CloseHandle.
Begin Listing 1
#include <stdio.h>
#include <windows.h> /* For the CreateThread prototype */
long WINAPI Add10(long); /* Function prototype */
HANDLE hUserFile; /*File that the user enters data into */
int BytesWritten, Count, DataValue;
void main(void)
{
int iID; /* Holds the thread ID for each thread */
HANDLE hThread;
/* Step 1: Let the user input some data. */
hUserFile = CreateFile("datafile",<parameters>);
for (Count = 0; Count < 100; Count++)
{
printf("Please enter next number: ");
scanf("%d", &DataValue);
}
WriteFile(hUserFile, &DataValue, sizeof(int),
&BytesWritten, NULL);
}
CloseHandle(hUserFile);
/* Dispatch a thread that does Step 2 (adds 10 to the data) */
hThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Add10,
NULL,0,&iID);
if(!hThread) <process error condition, cant create>;
else CloseHandle(hThread); /* Closes thread after the thread
finishes execution of the thread function */
/* Step 3: Let the user enter more data, because well still be
executing in the thread*/
}
long WINAPI Add10(long lParam) /* The Thread Function */
{
HANDLE hThreadFile; /* handle to the thread-created file */
int iTemp; /* gets the original value type in, and then gets 10
added to it */
hUserFile = CreateFile("Input datafile.dat",...);
hThreadFile = CreateFile("Output datafile.dat",...);
/* Read in data from hUserFile here */
iTemp += 10;
/* Write result to hThreadFile */
}
End Listing 1
10
Under Windows NT, thread creation and management is not limited to Win32
API calls. What can also be used, and is perhaps a better alternative, is the C run-time
library (the thread functions are in process.h). Specifically, the functions
_BeginThreadNT and _endthread can be used in place of CreateThread and CloseHandle.
This allows better performance for Windows NT applications, because the Win32 API is
a general 32-bit interface, and can be used on Windows 95 as well. CreateThread has
been proven to cause small memory leaks in Windows NT, which can build up over long
periods of thread execution. Also, _BeginThreadNT offers better control over thread
security. With these differences, however, the two functions take identical parameters.
To illustrate how _BeginThreadNT and _endthread can be used to implement
multithreading, another programming example has been provided (see listing 2). This
program creates 25 threads that are suspended on initial creation. As mentioned earlier, a
call to ResumeThread can be used to return each suspended process to the execution
state. Once all 25 threads is created and suspended, the program will prompt the user to
hit a key, which starts the execution of each thread, one-by-one. A call to
WaitForMultipleObjects will freeze the execution of code in main until each thread has
finished, and finally all thread handles will be closed.
Listing 2 shows that as the number of threads in a system increase, thread
synchronization becomes a bigger issue to the programmer.
11
Begin Listing 2
#include
#include
#include
#include
<windows.h>
<process.h>
<stdio.h>
<conio.h>
/* This function acts as the 'main' function for each new thread. */
static void threadMain(void *arg)
{
printf("Thread %2d has an ID of %u\n", (int)arg,
GetCurrentThreadId());
_endthread();
} /* End Function threadMain */
int main(void)
{
#define NTHREADS 25
HANDLE hThreads[NTHREADS];
Int i;
/* Create NTHREADS threads that are initially
suspended and that will run starting at threadMain(). */
for (i = 0; i < NTHREADS; i++)
{
SECURITY_ATTRIBUTES sa =
{
sizeof(SECURITY_ATTRIBUTES), /* structure size */
0, /* No security descriptor */
TRUE, /* Thread handle is inheritable*/
};
DWORD
threadId;
hThreads[i] = (HANDLE)_beginthreadNT(
threadMain, /* Thread starting address */
4096,
/* Thread stack size */
(void )i,
/* Thread start argument */
&sa,
/* Thread security */
CREATE_SUSPENDED, /* Create in
suspended state */
&threadId); // Thread ID.
if(hThreads[i] == INVALID_HANDLE_VALUE)
{
MessageBox(0,"Thread Creation Failed", Error",
MB_OK);
return 1;
}
printf("Created thread %2d with an ID of %u\n", i,
threadId);
} /* End loop through NTHREADS */
printf("\nPress a key to resume all threads\n\n");
getch();
/* Resume the suspended threads. */
12
End Listing 2
13
Conclusion
In recent years, the benefits of multithreading have become more apparent
to the end-user, and easier to implement software designers in the form of
operating systems that readily support it. This research paper has just scratched
the surface of the different techniques used in implementing multithreading in an
attempt to keep the CPU busy at all times, for maximum throughput of data in an
application.
Works Cited
Finger, Jonathan, Lightweight Tasks in C. Dr. Dobbs Journal April 1995: 48-50.
Prasad, Shashi, Weaving a Thread. Byte October 1995: 173-174.
Marrin, Ken, Multithreading Support Grows among Realtime Operating Systems.
Computer Design March 1993: 77-88.
Kerns, T., The Advantages of Multithreaded Applications. EE Evaluation Engineering
February 1998: 76, 78-79.
Silberschatz, Abraham, and Peter B. Galvin. Operating System Concepts.
Reading: Addison-Wesley Publishing Company, 1998.
Custer, Helen. Inside Windows NT. Redmond: Microsoft Press, 1993.
14
15