Programming with Threads Threads Sometimes called a lightweight
- Slides: 24
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 § 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:
Threads Process 0 regs mem Process 1 code regs mem code All threads in a process share the same memory space
Single Threaded and Multithreaded Process Models Multithreaded Process Model Single-Threaded Process Model Process Control Block User Address Space Thread Control Block Thread Control Block Process Control Block User Stack User Address Space Kernel Stack User Stack Kernel Stack Thread
Why Threads? § § § Software Portability Latency Hiding Scheduling and Load Balancing Speed Ease of Programming and Widespread use § Program Maintenance
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?
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
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
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);
#include <pthread. h> #include <stdio. h> int print_message_function( void *ptr ); int x = 1; main() { pthread_t thread 1, thread 2; int thread 1 result, thread 2 result; char *message 1 = "Hello"; char *message 2 = "World"; pthread_attr_t *pthread_attr_default = NULL; int print_message_function( void *ptr ) { char *message; message = (char *) ptr; printf("%s ", message); fflush(stdout); return x++; } printf("Beginn"); pthread_create( &thread 1, pthread_attr_default, (void*)&print_message_function, (void*) message 1); pthread_create(&thread 2, pthread_attr_default, (void*)&print_message_function, (void*) message 2); pthread_join(thread 1, (void *)&thread 1 result); printf("End thread 1 with %dn", thread 1 result); pthread_join(thread 2, (void *)&thread 2 result); printf("End thread 2 with %dn", thread 2 result); exit(0); }
#include <sys/types. h> #include <sys/socket. h> server() { SOCKET listen. Skt, new. Skt; struct sockaddr_in server. Name, client. Name; listen. Skt = socket(AF_INET, SOCK_STREAM, 0); //Fill in server. Name bind(listen. Skt, &server. Name, sizeof(server. Name)); listen(listen. Skt, 5); new. Skt = accept(listen. Skt, &client. Name, sizeof(client. Name)); // Fire off a thread to do communication using send and recv on new. Skt // Loop back and accept another connection close(skt); }
typedef struct myarg { int skt; int whatever; }My. Arg; … … pthread_attr_t *default = NULL; My. Arg *arg; while (!done) { new. Skt = accept(listen. Skt, &client. Name, sizeof(client. Name)); // Allocate and fill the argument structure arg = (My. Arg *)malloc(sizeof(My. Arg)); arg->skt = new. Skt; // Fire off a thread to do communication using send and recv on new. Skt pthread_create(&threads[j], default, Handle. Connection, (void *)arg); }
typedef struct myarg { int skt; int whatever; }My. Arg; … … void *Handle. Connection(void *arg) { int skt; char buffer[255]; // Don’t do this!!!! Allocate as much as you need! skt = (My. Arg *)arg->skt; recv(skt, buffer, bufflen, 0); // Wrap this in a while loop // Process the message send(skt, responselength, 0); }
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
Effects of False Sharing Shared variables In Same Cache Line Local variables • Multiple Threads • Writing to two variables • Placement • local stack variables • Right next to each other • 16 words apart • 32 words apart
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);
#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); }
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
/* 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); }
/* 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);
- Sometimes sweet sometimes sour
- Sometimes cold sometimes hot
- They say it only takes a little faith
- Sometimes you win some sometimes you lose some
- Drilling head contains
- Locomotor dance movements
- Sometimes called jbod
- Reading an empty input is an example of unobvious errors.
- Accounting is often call the "language of business" because
- Bpa bpi bpr
- Plain, unformatted text is sometimes called ascii text.
- Lightweight remote procedure call
- Slab vs cast vs splint
- Lightweight vs heavyweight framework
- Lightweight innovations for tomorrow
- Vehicle lightweight arresting device
- Posix threads
- "wam v"
- Susan suddenly stretched slowly.
- Lightweight concrete mix ratio
- Dartmouth russian
- Literal vs figurative language examples
- You have two lightweight metal spheres each hanging
- Lightweight rpc
- Lwapp to autonomous