WEBINAR:On-Demand

Introduction

This article tries to explain the conceptual aspect of multithreading programming. Much of the explanation is in context with Windows NT. Most of the material is derived from MSDN.

What Are Threads?

Windows NT's basic unit of execution is a thread. That means WIN NT does not execute processes; instead, it executes threads. Threads are code sequences that run multitasked on individual stacks. A thread has its own sequence of code, which gets executed in a concurrent fashion. So threads help us achieve concurrent processing. WIN NT Scheduler controls the execution of all the threads running in a system. In WIN NT, each thread has its own priority, numbered from 0 to 31, based on which WIN NT schedules the execution of each thread. The higher the priority number, the higher the thread's priority. A process may have a single thread or multiple threads. A single process has to have a minimum of one thread. Processes can spawn threads and can terminate threads. A thread can be in one of the three states at given time, such as:

Running The thread is currently running on one of the CPUs.

Waiting The thread is in a suspended state and cannot run until a specified event occurs.

Ready A thread is ready to run, but no processor is currently available.

Ready and running threads are called runnable threads. The runnable threads can utilize available CPU cycles. The number of currently running threads on a system is limited by the number of CPUs available. On a single processor system, the number of threads running at a given time is one. On a multiple processor system, the number of threads running at given time is equal to the number of processors.

When a CPU becomes available, the OS finds the highest priority queue with ready threads on it, removes the thread at the head of the queue, and runs it. This process is called a context switch. Each context switch adds a little overhead; as a result, the system will get sluggish as the number of threads increases. WIN NT is a pre-emptive multitasking system; this means that the amount of time for which a thread keeps running is decided by OS and not by the thread itself. If enough CPU time is available and no other higher priority threads are ready, the OS allows the running thread to complete its quota of time, which is called thread quantum. After a thread completes its thread quantum, the OS finds the ready thread at the head of highest priority queue and runs it. If a thread completes its thread quantum and a higher priority thread is ready, the OS pre-empts the currently running thread and runs the higher priority thread.

Why Multithreading?

There are several reasons we may need to use multithreading; the most important of them is to enhance your application's performance. For example, any application that has something to do in the background, irrespective of what is going on in the foreground (User interface); in such applications, there can be one worker thread, which performs a background job; and the main thread, which performs activities related to user interface.

Sometimes multithreaded application designs are more logical and less complex than the same without multithreading. An application which controls temperature receives temperature measurements from two pyrometers (temperature measuring devices) at regular intervals; the application should respond to these measurements in definite time (real time). It is more logical to have to have two threads running which accept temperature measurements from each pyrometer and send the response back.

So it is an important design criterion to have multiple threads or to go for a single threaded application. There is not a hard and fast rule available.

Where Are We Going?

In a multithreaded application, if the threads are independent of each other, it's much easier to design, develop, and debug such applications. But in the practical world, the picture is not so rosy. The threads are always dependent on each other and they share common resources. There starts the world of thread synchronization. In our next session we cover the concepts of thread synchronization.

Comments

Are there any simulated programs about threads?

Posted by tungnvn
on 08/15/2006 09:35am

I am teaching OSC (Operating System Concepts). It is difficult to explain concepts of threads or processes for student. I am looking for some programs which simulate these problems.

Waiting Threads

You didn't tell about many waiting threads with equal priority. Which comes first? This one which has waited a longer or a shorter time? To my mind it should be the thread waiting longer, but experiments with Windows 98 show that it is inverse. The thread which has waited at least comes first. How does this work? What is under the hood?

Please offer some examples for multithread.

Here's an Example

Posted by ZimProgC
on 05/01/2005 11:52pm

You have a MFC application that needs to populate a something by reading a very large file or database on load. If you did the population in the OnInitDialog the application would apear to not load up until the loading routine was finished. Putting the load routine into a thread and calling it from the OnInitDialog would allow the application to continue as normal and the user could exit the app if they chose to.

Similarly you might have an app that just calculates when a button is clicked. If your calculations max out the CPU then the application will appear to be non-responsive or very sluggish. If you had another button on the app to stop the function you wouldn't be able to click it and the window it's on might even fail to redraw. Putting the calculation routine into a separate thread will allow the rest of the app to be responsive since the thread the window runs in won't be busy doing the calculation.

Code:

Declare the thread function in your header as:

static UINT MyThreadFunc(LPVOID parent);

to start the thread:

AfxBeginThread(MyThreadFunc,(LPVOID)this);

The thread function itself:

UINT CMyDlg::MyThreadFunc(LPVOID parent)
{
//Use this pointer to access all of the members of CMyDlg (i.e. Dialog controls, etc)
CMyDlg* pParent=(CMyDlg*)parent;

Practical example for multithreading

After I've read some of your comments I guess most want to know where to apply multithreading.
I've got a good example for this:

I'm currently designind an activex-control for loading/displaying/editing images. I have images with 3500x2500 pixels, and, to preserve memory, i will have to convert them from tiff to dib for example. This process is very CPU-intensive, and if you have a multipage-tiff with 6 frames of this dimension, the user waits 1 or 2 minutes, until the first frame is displayed.

So I created a seperate thread, responsible for loading data. It fills a special structure, containing information which frame is already loaded, which is not. As soon as the first frame is loaded, it will be displayed, regardless how much frames there are to load.

I suggest seperate threads everywhere where blocking operation might occur. In my case, if loading of the first frame is to slow, the user can abort the load process...

Advertiser Disclosure:
Some of the products that appear on this site are from companies from which QuinStreet receives compensation. This compensation may impact how and where products appear on this site including, for example, the order in which they appear. QuinStreet does not include all companies or all types of products available in the marketplace.

Thanks for your registration, follow us on our social networks to keep up-to-date