1 / 24

Programming with Threads

Programming with Threads. Threads. Sometimes called a lightweight process smaller execution unit than a process Consists of: program counter register set stack space Threads share: memory space code section OS resources(open files, signals, etc.). Threads.

vrodriquez
Télécharger la présentation

Programming with 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. Programming with Threads

  2. Threads • Sometimes called a lightweight process • smaller execution unit than a process • Consists of: • program counter • register set • stack space • Threads share: • memory space • code section • OS resources(open files, signals, etc.)

  3. Threads • A process is defined to have at least one thread of execution • A process may launch other threads which execute concurrently with the process • Switching between threads is faster • No memory management issues, etc. • Mutual exclusion problems:

  4. regs Threads Process 0 Process 1 regs regs mem code code mem All threads in a process share the same memory space

  5. Single Threaded and Multithreaded Process Models Multithreaded Process Model Single-Threaded Process Model Thread Thread Thread Thread Control Block Thread Control Block Thread Control Block Process Control Block User Stack Process Control Block User Stack User Stack User Stack User Address Space Kernel Stack User Address Space Kernel Stack Kernel Stack Kernel Stack

  6. Why Threads? • Software Portability • Latency Hiding • Scheduling and Load Balancing • Speed • Ease of Programming and Widespread use • Program Maintenance

  7. Thread issues • How should threads be scheduled compared to processes? • Equal to processes • Within the parent processes quantum • How are threads implemented • kernel support (system calls) • user level threads • What are the issues?

  8. User-Level Threads • All thread management is done by the application • The kernel is not aware of the existence of threads • Thread switching does not require kernel mode privileges • Scheduling is application specific

  9. Kernel-Level Threads • Windows NT and Linux are examples of this approach • Kernel maintains context information for the process and the threads • Switching between threads requires the kernel

  10. POSIX Threads • Thread API available on many OS’s • #include <pthread.h> • cc myprog.c –o myprog -lpthread • Thread creation • int pthread_create(pthread_t * thread, pthread_attr_t * attr, void * (*start_routine)(void *), void * arg); • Thread termination • void pthread_exit(void *retval); • Waiting for Threads • int pthread_join(pthread_t th, void **thread_return);

  11. #include <pthread.h> #include <stdio.h> int print_message_function( void *ptr ); int x = 1; main() { pthread_t thread1, thread2; int thread1result, thread2result; char *message1 = "Hello"; char *message2 = "World"; pthread_attr_t *pthread_attr_default = NULL; printf("Begin\n"); pthread_create( &thread1, pthread_attr_default, (void*)&print_message_function, (void*) message1); pthread_create(&thread2, pthread_attr_default, (void*)&print_message_function, (void*) message2); pthread_join(thread1, (void *)&thread1result); printf("End thread1 with %d\n", thread1result); pthread_join(thread2, (void *)&thread2result); printf("End thread2 with %d\n", thread2result); exit(0); } int print_message_function( void *ptr ) { char *message; message = (char *) ptr; printf("%s ", message); fflush(stdout); return x++; }

  12. #include <sys/types.h> #include <sys/socket.h> server() { SOCKET listenSkt, newSkt; struct sockaddr_in serverName, clientName; listenSkt = socket(AF_INET, SOCK_STREAM, 0); //Fill in serverName bind(listenSkt, &serverName, sizeof(serverName)); listen(listenSkt, 5); newSkt = accept(listenSkt, &clientName, sizeof(clientName)); // Fire off a thread to do communication using send and recv on newSkt // Loop back and accept another connection close(skt); }

  13. typedef struct myarg { int skt; int whatever; }MyArg; … … pthread_attr_t *default = NULL; MyArg *arg; while (!done) { newSkt = accept(listenSkt, &clientName, sizeof(clientName)); // Allocate and fill the argument structure arg = (MyArg *)malloc(sizeof(MyArg)); arg->skt = newSkt; // Fire off a thread to do communication using send and recv on newSkt pthread_create(&threads[j], default, HandleConnection, (void *)arg); }

  14. typedef struct myarg { int skt; int whatever; }MyArg; … … void *HandleConnection(void *arg) { int skt; char buffer[255]; // Don’t do this!!!! Allocate as much as you need! skt = (MyArg *)arg->skt; recv(skt, buffer, bufflen, 0); // Wrap this in a while loop // Process the message send(skt, response, responselength, 0); }

  15. Thread Issues • Thread function only gets • One void * argument and void * return • How do you do more? • Reentrance • False Sharing • Not same global variable, but within cache line • Mutual Exclusion

  16. Effects of False Sharing • Multiple Threads • Writing to two variables • Placement • local stack variables • Right next to each other • 16 words apart • 32 words apart Shared variables In Same Cache Line Local variables

  17. Synchronization Primitives • int pthread_mutex_init( pthread_mutex_t *mutex_lock, const pthread_mutexattr_t *lock_attr); • int pthread_mutex_lock( pthread_mutex_t *mutex_lock); • int pthread_mutex_unlock( pthread_mutex_t *mutex_lock); • int pthread_mutex_trylock( pthread_mutex_t *mutex_lock);

  18. #include <pthread.h> void *find_min(void *list_ptr) pthread_mutex_t minimum_value_lock; int minimum_value, partial_list_size; main(){ minimum_value = MIN_INT; pthread_init(); pthread_mutex_init(&minimum_value_lock, NULL); /*inititalize lists etc, create and join threads*/ } void *find_min(void *list_ptr){ int *partial_list_ptr, my_min = MIN_INT, i; partial_list_ptr = (int *)list_ptr; for (i = 0; i < partial_list_size; i++) if (partial_list_ptr[i] < my_min) my_min = partial_list_ptr[i]; pthread_mutex_lock(minimum_value_lock); if (my_min < minimum_value) minimum_value = my_min; pthread_mutex_unlock(minimum_value_lock); pthread_exit(0); }

  19. Locking Overhead • Serialization points • Minimize the size of critical sections • Be careful • Rather than wait, check if lock is available • Pthread_mutex_trylock • If already locked, will return EBUSY • Will require restructuring of code

  20. /* Finding k matches in a list */ • void *find_entries(void *start_pointer) { • /* This is the thread function */ • struct database_record *next_record; • int count; • current_pointer = start_pointer; • do { • next_record = find_next_entry(current_pointer); • count = output_record(next_record); • } while (count < requested_number_of_records); • } • int output_record(struct database_record *record_ptr) { • int count; • pthread_mutex_lock(&output_count_lock); • output_count ++; • count = output_count; • pthread_mutex_unlock(&output_count_lock); • if (count <= requested_number_of_records) • print_record(record_ptr); • return (count); • }

  21. /* rewritten output_record function */ • int output_record(struct database_record *record_ptr) • { • int count; • int lock_status; • lock_status=pthread_mutex_trylock(&output_count_lock); • if (lock_status == EBUSY) { • insert_into_local_list(record_ptr); • return(0); • } • else { • count = output_count; • output_count += number_on_local_list + 1; • pthread_mutex_unlock(&output_count_lock); • print_records(record_ptr, local_list, • requested_number_of_records - count); • return(count + number_on_local_list + 1); • } • }

More Related