Site hosted by Angelfire.com: Build your free website today!

 
 

Thread Programming
Written by Jose Mari Reyes

Copyright(C)1999, Jose Mari Reyes
email:jet_reyes@jetemail.net
Manila, Philippines
 
No part of this document may be used or reproduced in any form or by any means, or stored in
a database or retrieval system, without prior written permission of the author. Making copies
of any part of this document for any purpose other than your own personal use is prohibited

This document is presented as is, without warranty of any kind, either express or implied,
respecting the contents of this document. The author disclaim all types of liabilities, loss
or damage caused or alleged to be caused directly or indirectly by this document.

 

Introduction

   Thread is a very exciting technology, knowing and using this technology helps to make application runs efficiently.  This document will shows a minimal information about threads, enough for the reader to create application with thread capabilities.  I am not an expert on this field. I know some of this technology which I think enough for me to make a thread enable application, this lead me to write this document to share knowledge to all. If you find misleading information or error please email me, but be kind enough to not to say ill words.  I spend some of my spare time to provide readers this information so that everybody may benefit from this technology.  I disclaim all liabilities that may arise from the use of any part of this material or document.
 
 
 
 

Platform

    The examples shown in this document was created using REDHAT LINUX 5.1 and Digital UNIX
OSF1 v3.2.  I compiled the code using the compiler that comes with both OS, the good and tested "cc" c compiler. Our sample will make use of the POSIX threads.  I cannot guarantee that the code presented on this document will work on all UNIX platform, a modification to the code might be needed.
 
 
 
 

The Thread, Thread against Process

   Threads are often called lightweight process. Compared with process, thread is small, relatively cheap in terms of CPU cost.  A process have its own address space, file descriptor and other resources.  A thread on the other hand shares all those that belongs to a process, thus a thread is essentially a stack, program counters and set of registers. There are two main kinds of threads, these are User-space threads and Kernel-supported threads.  User-space threads operates without the support from the kernel, their state is maintained within the user space, while the Kernel-supported threads gets it context switching and scheduling from the kernel itself. User-space threads run as fast as the Kernel-supported threads on a single processor machines but on multiple processor machines the latter take advantages of this because the kernel schedule each threads on a available processor, this let each thread to run in parallel. Context switching between two threads in a single process is cheaper against the context switching between two process.
 
 
 

Some Benefits of Threads


 
 

Thread Standards

    The ISO/IEC standard 9945-1:1996 also known as the ANSI/IEEE POSIX 1003.1-1995 includes 1003.1c this is the part that deals with thread.  In this document we will discuss portions of the POSIX thread standard and its implementation in the DEC OSF1 thread.
 
 
 
 

Creating Threads

    The call to the pthread_create function creates a new thread.  Sypnosis:

#include <pthread.h>

  int pthread_create(
       pthread_t *thread ,
       pthread_attr_t attr ,
       pthread_startroutine_t start_routine ,
       pthread_addr_t arg );

    This function takes 4 parameters, the first one, the *thread is the object of the thread created. The second one is the thread object attribute, you can use pthread_attr_default to specify default attribute. The third parameter is start_routine, this is the function executed as the new thread. The last one is the address copied and pass to the new thread.  The newly created thread is by default joined or undetach, to create detached thread see the function pthread_detach.
 
 
 
 

Detach Thread

    By default, the thread created is non-detached meaning the calling thread is to wait for the termination of the called thread. Sometimes it is good to create a detached thread to reclaim storage. Call this function when a thread object is no longer referenced.

Sypnosis:

 #include <pthread.h>

  int pthread_detach( pthread_t *thread );
 
 
 
 

Synchronizing Threads

    POSIX threads provides two synchronization primitives, the mutex and condition variable.  In our discussion we will use the first one.  Mutexes are simple locking mechanism that can be used to control access to the shared resource.  Remember that in thread everything is shared, if two threads will modifying the same resource at the same time, the data might get garbled.  Good example is when two or more threads are running on same process, each thread is going to write to a variable which is our shared resource, can you imagine if the first thread writes 1 and the second writes 0 at a time on the same variable. Get the picture? This problem can be handled by syncronization by letting each thread to write and lock the shared resources releasing it only when done.

    The minimal function to be called to do mutexes are:

int pthread_mutex_init(pthread_mutex_t *mutex , pthread_mutexattr_t attr );
int pthread_mutex_lock(pthread_mutex_t *mutex );
int pthread_mutex_unlock(pthread_mutex_t *mutex );
 
 
 
 

The Application

    All the necessary function to do our sample application has been tackled above, now that we are armed with sophisticated weaponry, we are now be able to create our first threaded application.  Our application will compute for the fibonacci of the set of number recursively, but instead of computing the fibonacci per number, we will do it simultaneously.  Below is the source for such project.
 

/************************************************************
  thread.c

  Written by Jose Mari Reyes
  Copyright(c)1999, Jose Mari Reyes

  Demonstration program using POSIX thread.
  compiled to LINUX and Digital Alpha v3.2
  if to be use on LINUX kindly define LINUX

***********************************************************/

#include <pthread.h>
#include <stdio.h>
 

#ifdef LINUX
#define pthread_attr_default  0
#endif
 

pthread_mutex_t  mutex;       /* mutex object */
int              t_count;      /* thread count */
 
 

struct Param
{
    int NTIMES;
    int NUMBER;
};

struct Param  P[5];
 
 

unsigned fib(x)       /* compute fibonacci number recursively */
int x;

{

     if (x > 2)

 return (fib(x - 1) + fib(x - 2));

     else
 return (1);

}
 
 

void fibo (int N)
{
   int i;
   unsigned value;

   printf("\nCreated thread number:%d Iteration:%d  Value:%d"
          ,N, P[N].NTIMES, P[N].NUMBER);
   fflush(stdout);

   t_count++;     /*increment thread count*/

 for (i = 1; i <= P[N].NTIMES; i++)

  value = fib(P[N].NUMBER);

        pthread_mutex_lock( &mutex);
        printf("\nfibo(%d, %d) = result:%u",P[N].NTIMES, P[N].NUMBER, value);
        fflush(stdout);
        pthread_mutex_unlock( &mutex);
        t_count--;     /* decrement thread count*/
        pthread_exit(NULL);
 

}
 
 

void main()
{
pthread_t  th1;
int        N;

    printf("\n\nPOSIX Thread sample program written by Jose Mari Reyes");
    printf("\nCopyright(C)1999, Jose Mari Reyes\n\n");

    pthread_mutex_init(&mutex, pthread_mutexattr_default);

    for (N = 0; N < 5; N++)
    {
       P[N].NTIMES = 40 * N + 10; P[N].NUMBER = 20 + N;
       pthread_create(&th1, pthread_attr_default, (void *) &fibo, (int *) N);
       pthread_detach(&th1);
    }

    sleep(1);
    while (t_count > 0)
        sleep(1);

    printf("\nprocess end..\n\n");

}/*end of thread.c*/
 
 

    Our source will compute for the fibonacci of the sets of numbers, the number of repetition and the value itself is stored in the array of param (see the structure param), these sets is shared throughtout the application because it is declared global.  Since our mutex object will be used by our function, we declared it as public mutex object.  The initialization of our mutex object is accomplished by the call to pthread_mutex_init, we dont have to modify its attribute.  The thread object is declared local to the main function since we are not going to maintain many thread object.  We create five(modifiable by adjusting the value of for loop)threads by placing the pthread_create function inside the for loop control structure, notice the last parameter, we passed the value of N to the fibo function so that the fibo function will know what's the index of its parameter.  We detach every thread created so that we avoid unfreed address when a thread dies or exit.  We call the sleep system function so that we can avoid a zero value on the t_count(we don't know which goes first) and we can avoid our program to take all the CPU time.  In the function fibo we must synchonize the call to the printf function since this is not a thread safe function, if we don't use any type of synchronization, the output of printf might get garbled.  The t_count is incremented each time a thread is created and decremented each time the thread exit.  The call to the pthread_exit function terminates a thread.
 
 
 
 

Compiling Our Application

    To compile the source, we use the cc compiler.  This compiler as far as my knowledge goes is the standard compiler and included in any UNIX Operating System.  Below is our makefile.
(a modification to the compiler's switch might be needed if the app will be compiled to other platform, in our case we compiled it to Digital Alpha v3.2).
 
 

# MAKEFILE for thread.c
# Written by Jose Mari Reyes
# makefile for DCE Thread Digital OSF

thread: thread.c
 cc -D_REENTRANT -o thread thread.c -lpthreads -lc_r
 
 
 
 

What do we covered

    Our sample application have covered some basic aspect of thread programming.  We have covered the method of creating thread, synchronization, inter-thread commmunication (the structure param is shared), detaching a thread and exiting from thread.
 
 
 
 

Few Things To Try

    The source code presented above is somewhat crude, you can try modifying the code, for example you can use semaphore instead of simple mutex lock synchronization method or you can try new method to wait for a single thread to terminate.
 
 
 
 

Links to Source of Information(WEB)

Getting Started With POSIX Threads by  Tom Wagner  and Don Towsley
Department of Computer Science University of Massachusetts at Amherst

General PThread Information

Multithreading in Windows NT

comp.programming.threads FAQ

Linux Threads Frequently Asked Questions (FAQ) by Sean Walton, KB7rfa
 
 
 

This page have been accessed

Email: jet_reyes@jetemail.net

Jet Center, The Joey Reyes Software Homepage Copyright (C)1999, Jose Mari Reyes

Redhat Linux is trademark of Redhat Inc.
POSIX is an IEEE specification.
OSF1 is a trademark of Digital Equipment Corp.