Threads

 

Single and Multithreaded Processes

 

 

 

Benefits: Responsiveness & Resource Sharing

 

 

Multithreaded Server Architecture

 

 

 

 

Description: 4

 

Pthreads

ü A POSIX standard API for thread creation and synchronization

ü Common in UNIX operating systems (Solaris, Linux, Mac OS X)

 

EXAMPLE:

âthrd2-posix.c:

int             sum;      /* this data is shared by the thread(s) */
int             sum2;     /* this data is shared by the thread(s) */

void           *runner(void *param);   /* the thread */
void           *runner2(void *param);  /* the thread */

int main(int argc, char *argv[])
{
    pthread_t       tid;  /* the thread identifier */
    pthread_t       tid2; /* the thread identifier */
    pthread_attr_t  attr; /* set of attributes for the thread */

    /* get the default attributes */
    pthread_attr_init(&attr);

    /* create the thread */
    pthread_create(&tid, &attr, runner, argv[1]);
    /* create the  2nd thread */
    pthread_create(&tid2, &attr, runner2, argv[1]);

    /* now wait for the thread to exit */
    pthread_join(tid, NULL);
    pthread_join(tid2, NULL);

    printf("sum = %d\n", sum);
    printf("sum2 = %d\n", sum2);
}


void  *runner(void *param)
{
    int             i, upper = atoi(param);
    sum = 0;

    if (upper >= 0) {
         for (i = 0; i <= upper; i++) {
             sum += i;
                }
    }
    pthread_exit(0);
}

void  *runner2(void *param)
{
    int             i, upper = atoi(param);
    sum2 = 0;

    if (upper >= 0) {
         for (i = 0; i <= upper; i++) {
             sum2 += pow(2, i);
                }
    }
    pthread_exit(0);
}
 

 

To execute:

 

% thrd2-posix  1

sum = 1

sum2 = 3

 

% thrd2-posix  20

sum = 210

sum2 = 2097151

 

Java Threads

ü Java threads are managed by the JVM

ü Typically implemented using the threads model provided by underlying OS

 

EXAMPLE:

 

âSimpleThread.java:

 

public class SimpleThread extends Thread {

  private int countDown = 50;

  private static int threadCount = 0;

  private int threadNumber = ++threadCount;

 

  public SimpleThread() {

    System.out.println("Making " + threadNumber);

  }

  public void run() {

    while(true) {

      System.out.println("Thread " +

        threadNumber + "(" + countDown + ")");

      if(--countDown == 0) return;

    }

  }

 

  public static void main(String[] args) {

    for(int i = 0; i < 5; i++)

      new SimpleThread().start();

    System.out.println("All Threads Started");

  }

}

 

To execute:

 

% java SimpleThread

 

 

 


Threading Issues

·      Semantics of fork() and exec()

Does fork() duplicate only the calling thread or all threads?

No, it does not duplicate any of the threads.

âExample:  thread-fork.c

main(int argc, char *argv[])

{

   pthread_create(&tid, &attr, runner1, 0);

   if ( fork() == 0){

       runner2();

       exit(0);

   }

   else {

      pthread_join(tid, NULL);

      printf("thread done\n");

      wait(NULL);

      printf("child  process done\n");

   }

}

void *runner1()

{

   int i;

   for(i=0;i<=7;i++) {

      printf("HI %d\n", i);

      sleep(i);

   }

}

void *runner2()

{

   int i;

   for(i=0;i<=7;i++) {

      printf("HI %c\n", i+'a');

      sleep(i);

   }

}

 

To execute:

 

%  thread-fork

HI 0

HI 1

HI a

HI b

HI 2

HI c

HI d

HI 3

HI e

HI 4

HI f

HI 5

Etc...

 

Signal Handling

Signals are used in UNIX systems to notify a process that a particular event has occurred

A signal handler is used to process signals

Signal is generated by particular event

Signal is delivered to a process

Options:

Deliver the signal to the thread to which the signal applies

Deliver the signal to every thread in the process

Deliver the signal to certain threads in the process

Assign a specific thread to receive all signals for the process

 

In UNIX:

·       The signal is delivered to EVERY  process in the program

·       The parent process of all threads gets the signal and  NONE  of the threads gets it.

 

âExample 1:  thread-fork-signal.c

int
main(int argc, char *argv[])
{

   pthread_t       tid; 
   pthread_attr_t  attr;

   pthread_attr_init(&attr);

   signal(SIGINT, SIG_IGN);
   pthread_create(&tid, &attr, ThreadRunner, 0);
   if (fork() == 0) {
   ChildRunner();
        exit(0);
   }
   ParentRunner();
   wait(NULL);
   printf("child  process done\n");

   pthread_join(tid, NULL);
   printf("thread done\n");
}

void *ParentRunner()
{
   int i;

   printf("\nParentRunner started, PID: %d\n", getpid());
   for(i=0;i<=7;i++) {
      printf("Parent: %c\n", i+'A');
      sleep(i);
   }
}

void *ThreadRunner()
{
   int i;
   signal(SIGINT, ThreadSIGhandler);

   printf("\nThreadRunner started, PID: %d\n", getpid());
   for(i=0;i<=7;i++) {
      printf("Thread: %d\n", i);
      sleep(i);
   }
}

void *ChildRunner()
{
   int i;
   signal(SIGINT, ChildSIGhandler);

   printf("\nChildRunner started, PID: %d\n", getpid());

   for(i=0;i<=7;i++) {
      printf("Child: %c\n", i+'a');
      sleep(i);
   }
}
void ThreadSIGhandler(int sig)
{
    signal(sig, ThreadSIGhandler);
    printf("\nPID: %d", getpid());
    psignal(sig, "\nReceived ThreadSIGhandler signal");
    printf("pauseing...\n\n");
    pause();
}
void ChildSIGhandler(int sig)
{
    signal(sig, ChildSIGhandler);
    printf("\nPID: %d", getpid());
    psignal(sig, "\nReceived ChildSIGhandler signal");
    printf("pauseing...\n\n");
    pause();
}

 

 

To execute:

 

%  thread-fork-signal

 

Type: CTRL-C

 

·      Thread Pools

Create a number of threads in a pool where they await work

Advantages:

Usually slightly faster to service a request with an existing thread than create a new thread

Allows the number of threads in the application(s) to be bound to the size of the pool

·      Thread Specific Data

Allows each thread to have its own copy of data

Useful when you do not have control over the thread creation process (i.e., when using a thread pool)

 

 

 

 


EXAMPLES of Threaded Servers:

âEchoServerThread.c:

Int main(void)
{
    int             len, listenfd, connfd;
    struct sockaddr_in servaddr, cliaddr;
    char            buff[512];
    int             nread;
    pthread_t       tid;
    pthread_attr_t  attr;

    if ( (listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1 ) {
         printf ("error\n");
         exit(-1);
    }

    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(10123);

    if ( bind(listenfd, (SA *) & servaddr, sizeof(servaddr)) < 0) {
            printf("can not bind\n");
            exit(-1);
     }

    listen(listenfd, 0);

    pthread_attr_init(&attr);

    for (;;) {
         len = sizeof(cliaddr);
         connfd = accept(listenfd, (SA *) & cliaddr, &len);

printf("connection from: %s:%d\n", inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port));

              pthread_create(&tid, &attr, &EchoToClient, (void *) connfd);

        }
}

void  *EchoToClient(void *sockfd)
{
    int             nread;
    char            buffer[512];
    for (;;) {
         nread = read((int) sockfd, buffer, 512);
         if (nread == 0)
             pthread_exit(0);
             // exit(0);
         write((int) sockfd, buffer, nread);
    }
}

 

To execute:

 

% EchoServerThread  

 

ü In another window for the same host:

 

% EchoClientFork    localhost     10123

 

ü In another window for the same host:

 

% EchoClientFork    localhost     10123

 

ü Repeat for any number of other windows.

 

âEchoServerThreadJava:

class EchoToClient extends Thread {

  private Socket socket;

  private BufferedReader in;

  private PrintWriter out;

 

  public EchoToClient(Socket s) throws IOException {

    socket = s;

    in = new BufferedReader( new InputStreamReader( socket.getInputStream()));

        out = new PrintWriter( new BufferedWriter(

                  new OutputStreamWriter(socket.getOutputStream())), true);

    start();

  }

  public void run()  {

    try {

      while (true) { 

        String str = in.readLine();

        if (str.length() == 0 )

                 System.exit(0);

        else

        out.println(str);

      }

    } catch(IOException e) {

    }

  }

}

 

public class EchoServerThreadJava { 

  public static void main(String[] args)

      throws IOException {

    ServerSocket s = new ServerSocket(10123);

    try {

      while(true) {

        Socket socket = s.accept();

        try {

          new EchoToClient (socket);

        } catch(IOException e) {

 

        }

      }

    } catch(IOException e) {

    }

  }

}

 

To execute:

 

% java EchoServerThreadJava 

 

ü In another window for the same host:

 

% EchoClientFork    localhost     10123

 

ü In another window for the same host:

 

% EchoClientFork    localhost     10123

 

ü Repeat for any number of other windows.