Top Banner
Threads Chapter 26
27

Threads

Jan 19, 2016

Download

Documents

molimo

Threads. Chapter 26. Threads. Light-weight processes Each process can have multiple threads of concurrent control. What’s wrong with processes? fork() is expensive 10 to 100 times slower Copy of everything in parent. Inter process communication - PowerPoint PPT Presentation
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Threads

Threads

Chapter 26

Page 2: Threads

Threads Light-weight processes

Each process can have multiple threads of concurrent control.

What’s wrong with processes? fork() is expensive

10 to 100 times slower Copy of everything in parent.

Inter process communication For returning information from child to parent

Page 3: Threads

Threads… Shared components

Global memory Instructions Most data Open descriptors (files, sockets etc) Signal handlers

Not shared Registers, Program counter, stack pointer Thread ID Stack Errno Priority

Page 4: Threads

Advantages of Threads Light-weight

Lower Context Switching Overhead Fewer OS resources

Shared State Don’t need IPC-like mechanism to

communicate between threads of same process

Page 5: Threads

Disadvantages of Threads Shared State!

Global variables are shared between threads. Accidental changes can be fatal.

Many library functions are not thread-safe Library Functions that return pointers to static

internal memory. E.g. gethostbyname()

Lack of robustness Crash in one thread will crash the entire process.

Page 6: Threads

Creation Thread equivalent of fork()

int pthread_create(pthread_t * thread,

pthread_attr_t * attr,

void * (*start_routine)(void *),

void * arg

);

Returns 0 if OK, and non-zero (> 0) if error.

Page 7: Threads

Termination

Thread Termination Return from initial function. void pthread_exit(void * status)

Process Termination exit() called by any thread main() returns

Page 8: Threads

Waiting for child thread

int pthread_join( pthread_t tid, void **status)

Equivalent of waitpid()for processes

Page 9: Threads

Detaching a thread

The detached thread can act as daemon thread

The parent thread doesn’t need to wait

int pthread_detach(pthread_t tid)

Detaching self : pthread_detach(pthread_self())

Page 10: Threads

Echo client-server

ReadThread

WriteThread

ReadThread

WriteThread

Read Write WriteReadClient1 Client2

Server

S1 S2

listenfd

Page 11: Threads

Thread-based Echo Server

Page 12: Threads

main()

{int listenfd, connfd;

int len;

pthread_t tid;

/* Start the usual way */

listenfd = Socket(…);

Bind(listenfd, …);

Listen(listenfd, …)

for ( ; ; ) {len = addrlen;

connfd = Accept(listenfd, …);

/* Create a thread in service_func routine */

Pthread_create(&tid, NULL, service_func, ???? );

}

}

How to pass connfd?

(void *) arg

Page 13: Threads

main()

{int listenfd, connfd;

int len;

pthread_t tid;

/* Start the usual way */

listenfd = Socket(…);

Bind(listenfd, …);

Listen(listenfd, …)

for ( ; ; ) {len = addrlen;

cptr = Malloc(sizeof(int));

*cptr = Accept(listenfd, …);

/* Create a thread in service_func routine */

Pthread_create(&tid, NULL, service_func, (void *) cptr);

}

}

Page 14: Threads

void * service_func(void *arg){

int local_connfd;

/* release parent from waiting */Pthread_detach(pthread_self());

/* extract connfd from argument */local_connfd = *((int *) arg);free(arg);

/* receive and echo client’s message See Figure 5.3, page 124, Steven’s book*/

str_echo(local_connfd);

/* Terminate the connection */Close(local_connfd);

return(NULL);

}

Page 15: Threads

Thread-based Echo Client

Why is single threaded client not good enough?

Multi-threaded Client

Page 16: Threads

int sockfd;FILE *fp;

main(){

pthread_t tid;fp = fopen(…);

/* Start the usual way */sockfd = Socket(…);…Connect(…);

/* Create a thread to send data */Pthread_create(&tid, NULL, write_func, NULL);

/* read data from sockfd */read_func();

/* wait for child thread */Pthread_join(tid, NULL);

}

Page 17: Threads

void * write_func(void *arg)

{

char sendline[MAXLINE];

while( more data in fp)Read from fp into sendline[];

Write sendline[] into sockfd;

Shutdown(sockfd, SHUT_WR);

return(NULL);

}

void read_func()

{

char recvline[MAXLINE];

while ( more data from sockfd)

Read from sockfd into recvline[];

Write from recvline[] to stdout;

}

Page 18: Threads

Locking in Threads

Page 19: Threads

Mutex – for mutual exclusion

int counter = 0;

void *thread_func(void *arg){

int val;

/* unprotected code – why? */val = counter;counter = val + 1;

return NULL;}

Page 20: Threads

Mutex…int counter = 0;ptread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void *thread_func(void *arg){

int val;

/* protected by mutex */Pthread_mutex_lock( &mutex );val = counter;counter = val + 1;Pthread_mutex_unlock( &mutex );

return NULL;}

Page 21: Threads

Condition Variable – for signaling

Think of Producer – consumer problem

Producers and consumers run in separate threads.

Producer produces data and consumer consumes data.

Producer has to inform the consumer when data is available

Consumer has to inform producer when buffer space is available

Page 22: Threads

Without Condition Variables

Page 23: Threads

/* Globals */

int data_avail = 0;

pthread_mutex_t data_mutex = PTHREAD_MUTEX_INITIALIZER;

void *producer(void *)

{

Pthread_mutex_lock(&data_mutex);

Produce data

Insert data into queue;

data_avail=1;

Pthread_mutex_unlock(&data_mutex);

}

Page 24: Threads

void *consumer(void *)

{

while( !data_avail );

/* do nothing – keep looping!!*/

Pthread_mutex_lock(&data_mutex);

Extract data from queue;

if (queue is empty)

data_avail = 0;

Pthread_mutex_unlock(&data_mutex);

consume_data();

}

Page 25: Threads

With Condition Variables

Page 26: Threads

int data_avail = 0;

pthread_mutex_t data_mutex = PTHREAD_MUTEX_INITIALIZER;

pthread_cont_t data_cond = PTHREAD_COND_INITIALIZER;

void *producer(void *)

{

Pthread_mutex_lock(&data_mutex);

Produce data

Insert data into queue;

data_avail = 1;

Pthread_cond_signal(&data_cond);

Pthread_mutex_unlock(&data_mutex);

}

Page 27: Threads

void *consumer(void *)

{

Pthread_mutex_lock(&data_mutex);

while( !data_avail ) {

/* sleep on condition variable*/

Pthread_cond_wait(&data_cond, &data_mutex);}

/* woken up */

Extract data from queue;

if (queue is empty)

data_avail = 0;

Pthread_mutex_unlock(&data_mutex);

consume_data();

}