1 / 41

Threads

Threads. Dr. Yingwu Zhu. Threaded Applications. Web browsers: display and data retrieval Web servers Many others. Processes vs. Threads. A thread exists within a process Threads are a finer-grained unit of execution than processes

harrisjuan
Download Presentation

Threads

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  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.

  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 –pthreador $ 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 <pthread.h> • 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 <pthread.h> #include <stdio.h> void * entry_point(void *arg) { printf("Hello world!\n"); return NULL; } int main(intargc, char **argv) { pthread_tthr; 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 <pthread.h> #include <stdio.h> void * entry_point(void *arg) { printf("Hello world!\n"); pthread_exit(NULL); //return NULL; } int main(intargc, char **argv) { pthread_tthr; 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 <pthread.h> #include <stdio.h> void * entry_point(void *arg) { printf("Hello world!\n"); pthread_exit(NULL); //return NULL; } int main(intargc, char **argv) { pthread_tthr; 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 <pthread.h> #include <stdio.h> /* 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 < p->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 <integer-para>\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 <pthread.h> #include <stdio.h> 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); }

More Related