Download presentation
Presentation is loading. Please wait.
Published byJunior Holland Modified over 9 years ago
1
Threads Dr. Yingwu Zhu
2
Threaded Applications Web browsers: display and data retrieval Web servers Many others
3
Processes vs. Threads A thread exists within a process Threads are a finer-grained unit of execution than processes When invoking a program, Linux creates a new process and in that process creates a single thread, which runs program sequentially – This thread can creates additional threads – All threads run concurrently, the same program in the same process, but each thread may be executing a different part of the program
4
Processes vs. Threads When forking a child process, the child process duplicates its parent’s address space (or VM), and copies parent’s file descriptors and other things, initially running its parent’s program The child process can modify its memory, close file descriptors and the like, without affecting the parent process, and vice versa
5
Processes vs. Threads When a thread creates another thread – Noting is copied! – The creating and created threads share the address space (VM), file descriptors and other system resources (one change for all! Caution!) – If one thread calls exec(), then all the other threads are ended! Why?
6
Threads Basic unit of CPU utilization Each thread contains its own (my privacy!) – Thread ID – Program counter – Register set – Stack All threads in a process share (do not pollute the public area!) – Text section (program) – Heap – Data section (global variables) – File descriptors
7
Single and Multithreaded Processes
8
Why Multithreading? Creating processes are expensive! Responsiveness – Web browsers: one thread for interactivity while others are retrieving images Resource Sharing – share memory and resources of the process they belong to – Sharing code and data allow different threads of activity within the same address space Economy – Processes are expensive to create, and do context-switch – In Solaris Process creating is about 30 times slower Context-switch is about 5 times slower Utilization of MP Architectures – A single-threaded process can only run on one CPU
9
Thread Type User threads Kernel threads Three primary thread libraries: – POSIX Pthreads (user & kernel): our case study – Win32 threads (kernel-level) – Java threads (depending on OS)
10
User Threads Thread management (creation, scheduling) done by user-level threads library – No kernel resources allocated to the threads Drawback – Blocking system call suspends other threads in the same process, I/O – a single thread can monopolize the timeslice thus starving the other threads within the same process – no way of taking advantage of SMPs – cooperatively scheduled: a running thread must explicitly "yield" to allow another thread to run. A thread can be scheduled to run in any thread in the same process. cooperatively scheduled
11
Kernel Threads Supported by the Kernel Advantages – Non-blocking thread execution (Similar to processes, when a kernel thread makes a blocking call, only that thread blocks ) – Multi-processors (threads on different processors) – No need to worry about starving other threads, preemptive scheduling Drawback – Slower to create and manage than user-level (kernel resource allocation) Examples – Windows XP/2000, Solaris – Linux – Tru64 UNIX, Mac OS X
12
Multithreading Models Many-to-one One-to-one Many-to-many Reading in textbook, Chapter 4
13
Case Study: Pthread How to Compile Creating and destroying threads How to use POSIX threads
14
Reading Materials Reading posted suppl. material on threads – 4.1 in the chapter
15
How to compile? $ gcc –Wall –o proj proj.c –pthread or $ g++ –Wall –o proj proj.cpp –pthread – The option specifies that pthreads library should be linked (libpthread: pthread APIs) – causes the complier to properly handle multiple threads in the code that it generates – Other platform/compiler may user other options, eg., -lpthread #include – All thread functions and data types are declared in the header file
16
Creating Threads int pthread_create (pthread_t *thread_id, pthread_attr_t *attr, void *(*thread_fun)(void *), void *args); -The #1 para returns thread ID (a unique ID per thread) The #2 para pointing to thread attr. NULL represents using the default attr. settings; controls details of how the thread interacts with the rest of the program -The #3 para as pointer to a function the thread is to execute, of the type: void* (*) (void*) The function receives an argument in #4 and return data from the thread to the creator; entry point of the created thread’s execution! -The #4 para is the arguments to the function -Return 0 on success; failure otherwise
17
Creating Threads pthread_create() A call to pthread_create returns immediately, and the original thread continues executing the instructions following the call Meanwhile, the new thread begins executing the thread function. Simply put, they run concurrently competing for CPU cycles. Hard to predict the execution order (that is why we study Synchronization later)
18
Creating Threads #include void * entry_point(void *arg) { printf("Hello world!\n"); return NULL; } int main(int argc, char **argv) { pthread_t thr; if(pthread_create(&thr, NULL, &entry_point, NULL)) { printf("Could not create thread\n"); return -1; } if(pthread_join(thr, NULL)) { printf("Could not join thread\n"); return -1; } return 0; }
19
Thread Terminates & Return Value Pthreads terminate when the function returns, or the thread calls pthread_exit() int pthread_exit(void *status); – status is the return value of the thread – A thread_fun returns a void*, so calling return (void *) is the equivalent of this function – the pthread_exit() routine does not close files; any files opened inside the thread will remain open after the thread is terminated
20
Example #include void * entry_point(void *arg) { printf("Hello world!\n"); pthread_exit(NULL); //return NULL; } int main(int argc, char **argv) { pthread_t thr; if(pthread_create(&thr, NULL, &entry_point, NULL)) { printf("Could not create thread\n"); return -1; } if(pthread_join(thr, NULL)) { printf("Could not join thread\n"); return -1; } return 0; }
21
Joining Threads int pthread_join(pthread_t thread_id, void **status) – #1 para: the thread ID of the thread to wait for – #2 para: receive the finished thread’s return value One thread can wait (or block) on the termination of another by using pthread_join() You can collect the exit status of all threads you created by pthread_join(), via status Similar to system call “wait()” in processes
22
Example #include void * entry_point(void *arg) { printf("Hello world!\n"); pthread_exit(NULL); //return NULL; } int main(int argc, char **argv) { pthread_t thr; if(pthread_create(&thr, NULL, &entry_point, NULL)) { printf("Could not create thread\n"); return -1; } if(pthread_join(thr, NULL)) { printf("Could not join thread\n"); return -1; } return 0; }
23
Kill Threads Kill a thread before it returns normally using pthread_cancel() But – Make sure the thread has released any local resources; unlike processes, the OS will not clean up the resources – Why? Threads in a process share resources
24
Passing Data to Threads #include /* Parameters to print_function. */ struct char_print_parms { /* The character to print. */ char character; /* The number of times to print it. */ int count; }; /* Prints a number of characters to stderr, as given by PARAMETERS, which is a pointer to a struct char_print_parms. */ void* char_print (void* parameters) { /* Cast the cookie pointer to the right type. */ struct char_print_parms* p = (struct char_print_parms*) parameters; int i; for (i = 0; i count; ++i) fputc (p->character, stderr); return NULL; }
25
Passing Data to Threads int main () { pthread_t thread1_id; pthread_t thread2_id; struct char_print_parms thread1_args; /* Create a new thread to print 30,000 ’x’s. */ thread1_args.character = ’x’; thread1_args.count = 30000; pthread_create (&thread1_id, NULL, &char_print, (void*)&thread1_args); /* Create a new thread to print 20,000 o’s. */ thread1_args.character = ’o’; thread1_args.count = 20000; pthread_create (&thread2_id, NULL, &char_print, (void*)&thread1_args); return 0; }
26
Passing Data to Threads One argument as void* Common practice – Pass a pointer to some structure or array of data The above program example has a problem – thread1_args – Solution?
27
Passing Data to Threads int main () { pthread_t thread1_id; pthread_t thread2_id; struct char_print_parms thread1_args; struct char_print_parms thread2_args; /* Create a new thread to print 30,000 ’x’s. */ thread1_args.character = ’x’; thread1_args.count = 30000; pthread_create (&thread1_id, NULL, &char_print, (void*)&thread1_args); /* Create a new thread to print 20,000 o’s. */ thread2_args.character = ’o’; thread2_args.count = 20000; pthread_create (&thread2_id, NULL, &char_print, (void*)&thread2_args); return 0; }
28
Passing Data to Threads One argument as void* Common practice – Pass a pointer to some structure or array of data
29
Example on Passing Data struct thread_data{ int thread_id; int sum; char *message; }; struct thread_data thread_data_array[NUM_THREADS]; //global void *PrintHello(void *threadarg) { struct thread_data *my_data;... my_data = (struct thread_data *) threadarg; taskid = my_data->thread_id; sum = my_data->sum; hello_msg = my_data->message;... } int main (int argc, char *argv[]) {... thread_data_array[t].thread_id = t; thread_data_array[t].sum = sum; thread_data_array[t].message = messages[t]; rc = pthread_create(&threads[t], NULL, PrintHello, (void *) &thread_data_array[t]);... }
30
Returning Results from Threads Thread function returns a pointer to void: void * Pitfalls in return value
31
Pitfall #1 void *thread_function ( void *) { int code = DEFAULT_VALUE; return ( void *) code ; } Only work in machines where integers can convert to a point and then back to an integer without loss of information
32
Pitfall #2 void *thread_function ( void *) { char buffer[64]; // fill up the buffer with sth good return ( void *) buffer; } This buffer will disappear as the thread function returns
33
Pitfall #3 void *thread_function ( void *) { static char buffer[64]; // fill up the buffer with sth good return ( void *) buffer; } It does not work in the common case of multiple threads running the same thread funciton
34
Right Way void *thread_function ( void *) { char* buffer = (char *)malloc(64); // fill up the buffer with sth good return ( void *) buffer; }
35
Right Way int main() { void *exit_state; char *buffer; …. pthread_join(tid, &exit_state); buffer = (char *) exit_state; printf(“from thread %d: %s\n”, tid, buffer); free(exit_state); }
36
Exercise Write a multithreaded program that calculates the summation of a non-negative integer in a separate thread (1+2+3+…+N) – The non-negative integer is from command-line parameter – Option 1: The summation result is kept in a global variable: int sum; // shared by threads – Option 2: The summation result is returned.
37
Step 1: write a thread function void *thread_sum(void *arg) { int i; int m = (int)(*arg); sum = 0; //initialization for (i = 0; i <= m; i++) sum += i; pthread_exit(0); }
38
Step 2: write the main() int sum; int main(int argc, char *argv[]) { pthread_t tid; if (argc != 2) { printf(“Usage: %s \n”, argv[0]); return -1; } int i = atoi(argv[1]); if (i < 0) { printf(“integer para must be non-negative\n”); return -2; } pthread_create(&tid, NULL, thread_sum, &i); //need to check return value pthread_join(tid, NULL); //need to check return value printf(“sum = %d\n”, sum); }
39
Exercise Write a program that creates 10 threads. Have each thread execute the same function and pass each thread a unique number. Each thread should print “Hello, World (thread n)” five times where ‘n’ is replaced by the thread’s number. Be sure the program doesn’t terminate until all the threads are complete. (Try running your program on more than one machine. Are there any differences in how it behaves?)
40
Exercise Which of the following components of program state are shared across threads in a multithreaded process? a. register values b. heap memory c. Global variables d. stack memory
41
What is output? #include int value = 0; void* runner(void* param); int main(int argc, char* argv[]) { int pid; pthread_t tid; pid = fork(); if (!pid) { pthread_create(&tid, NULL, runner, NULL); pthread_join(tid, NULL); printf(“CHILD: value= %d\n”, value); } else if (pid>0) { wait(NULL); printf(“PARENT: value = %d\n”, value); } void* runner (void* param) { value = 5; phread_exit(0); }
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.