1 / 39

第十一单元 线程:小心你的邻居

第十一单元 线程:小心你的邻居. What This Unit is About. This lecture introduces the concepts and more specific calls to handle the real world of POSIX threads programming. In the real world, a programmer needs to worry about protecting data resources from

Download Presentation

第十一单元 线程:小心你的邻居

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. 第十一单元 线程:小心你的邻居 中山大学-AIX应用程序开发

  2. What This Unit is About • This lecture introduces the concepts and more specific calls to handle • the real world of POSIX threads programming. In the real world, a • programmer needs to worry about protecting data resources from • simultaneous thread updates. A programmer may also be interested in • controlling when a given thread executes and how fast it executes. • What You Should Be Able to Do • After completing this unit, you should be able to: • Protect data resources from multi-thread usage. • Control thread execution. • How You Will Check Your Progress • You can check your progress by completing: • Lab exercise 12 • References: • AIX 5L online documentation

  3. Unit Objectives • Protect data resources from multithread usage. • Control thread execution

  4. Protecting Data Resources

  5. Handling Global Data: Mutex

  6. Handling Global Data Example (1 of 2) /* global.c */ #include <stdio.h> #include <stdlib.h> #include <pthread.h> int g_count; int g_done; pthread_mutex_t g_count_mutex; void * callFunc(void * notused) { int i; printf("I'm in the child thread now....\n"); for(i=0;i<10;i++) { pthread_mutex_lock(&g_count_mutex); g_count++; pthread_mutex_unlock(&g_count_mutex); printf("Count in CHILD is %d\n", g_count); sleep(1); } g_done = 1; /* Child is done with the mutex */ pthread_exit(NULL); }

  7. Handling Global Data Example (1 of 2) main() { pthread_t callThd; int ret; int i; g_count=0; g_done=0; pthread_mutex_init(&g_count_mutex,NULL); ret=pthread_create(&callThd, NULL, callFunc, NULL); if(ret) { printf("problems on creating thread\n"); exit(EXIT_FAILURE); } for(i=0;i<10;i++) { pthread_mutex_lock(&g_count_mutex); g_count++; pthread_mutex_unlock(&g_count_mutex); printf("Count in PARENT is %d\n", g_count); sleep(1); } while (!g_done) sleep(1); pthread_mutex_destroy(&g_count_mutex); pthread_exit(NULL); }

  8. Thread Specific Data: Initialization

  9. Thread Specific Data: Usage And Destruction

  10. Thread Specific Data: Example (1 of 2) /* tsd.c */ #include <pthread.h> pthread_key_t count_key; void * thread_starter(void * TID) { int * ptr; int ThreadID; ThreadID=*(int *)TID; ptr=(int *) malloc(sizeof(int)); pthread_setspecific(count_key, ptr); *ptr=0; (*ptr)++; subfunc(); (*ptr)++; printf("Thread %d's count should be 3 now. The pointer says:%d\n",ThreadID, *ptr); *(int *)TID = 0; subfunc(void) int * local_p; local_p=pthread_getspecific(count_key); (*local_p)++; }

  11. Thread Specific Data: Example (2 of 2) void count_key_destructor(void * Data) { free(Data); } main() { pthread_t thd1; pthread_t thd2; int tid1=1, tid2=2; pthread_key_create(&count_key, count_key_destructor); pthread_create(&thd1, NULL, thread_starter, (void *)&tid1); pthread_create(&thd2, NULL, thread_starter, (void *)&tid2); while (tid1 != 0 || tid2 != 0) sleep(1); while(pthread_key_delete(count_key) != 0) sleep(1); pthread_exit(NULL); }

  12. Handling Logic Static Data BEFORE funca() { static int count = 0; count++; printf("count is %d\n", count); } main() { funca(); funca(); } AFTER funca(short funca_count) { printf("count is %d\n", funca_count); } main() { short count = 1; funca(count); count++; funca(count); }

  13. 线程安全函数和可重入函数 • 线程安全函数 • 可重入函数

  14. Controlling Execution • Create • Exit • Wait/Interrupt • Cancel • Schedule • Other

  15. Condition Variable Logic

  16. Condition Variable Calls

  17. Condition Wait Implementation

  18. Condition Wait Example (1 of 2) /* condwait.c */ #include <signal.h> #include <stdio.h> #include <pthread.h> int Ready=0; pthread_mutex_t m; pthread_cond_t cv; void * slave(void * threadID) { int threadNum = *(int *) threadID; pthread_mutex_lock(&m); while(Ready != 1) pthread_cond_wait(&cv, &m); pthread_mutex_unlock(&m); printf("Thread %d continuing.... \n",threadNum); *(int *)threadID = 0; pthread_exit(NULL); } main() { pthread_t thd1; pthread_t thd2; pthread_t thd3; int j1=1, j2=2, j3=3; pthread_mutex_init(&m,NULL); pthread_cond_init(&cv,NULL); pthread_create(&thd1, NULL, slave, (void * )&j1); pthread_create(&thd2, NULL, slave, (void * )&j2); pthread_create(&thd3, NULL, slave, (void * )&j3);

  19. printf("Main doing work....\n"); sleep(5); /* Simulate work */ pthread_mutex_lock(&m); Ready=1; pthread_cond_broadcast(&cv); pthread_mutex_unlock(&m); printf("Main ready for others and continuing on.... \n"); sleep(5); /* Wait for children to terminate * (using pthread_join with undetached * children would be better) */ while ( j1 != 0 || j2 != 0 || j3 != 0 ) sleep(1); pthread_mutex_destroy(&m); pthread_cond_destroy(&cv); pthread_exit((void *) 0); }

  20. Master/Slave Implementation

  21. Master/Slave Example (1 of 2) /* master.c */ #include <signal.h> #include <stdio.h> #include <pthread.h> int jobInfo[25]; int jobAvail = 0; int jobPtr=0; /* job data passed to thread */ /* Boolean - # jobs available*/ /* job index for slave thread */ pthread_mutex_t m; pthread_cond_t cv; pthread_key_t key; /* used to protect cv */ /* causes slave to wait for new job */ /* provides TSD data for global jobInfo*/ void * slave(void * threadID) { int threadNum=*(int *) threadID; int * local_job; /* will store jobInfo data */ for(;;) { pthread_mutex_lock(&m); while(jobAvail < 1 && jobPtr < 25) pthread_cond_wait(&cv, &m); if (jobPtr == 25) { pthread_mutex_unlock(&m); /* We're done */ break; } local_job = (int *)malloc(sizeof(int)); /* allocate room for jobInfo*/ pthread_setspecific(key, (void *)local_job); *local_job = jobInfo[jobPtr]; /*global to TSD*/ jobPtr++; /* job handled count goes up */ jobAvail--; /* one less job left */ pthread_mutex_unlock(&m); /* Ready for others to continue*/ printf("Thread %d handling jobthreadNum, *local_job); with local_job info of %d\n", } *(int *)threadID = 0; pthread_exit(NULL); }

  22. Master/Slave Example (2 of 2) main() { pthread_t thd1; pthread_t thd2; pthread_t thd3; int j1=1,j2=2,j3=3; int i; /* thread IDs passed to threads */ /* job index for master thread */ pthread_mutex_init(&m,NULL); pthread_cond_init(&cv,NULL); pthread_create(&thd1, NULL, slave, (void * )&j1); pthread_create(&thd2, NULL, slave, (void * )&j2); pthread_create(&thd3, NULL, slave, (void * )&j3); for(i=0;i< 25;i++) /* create 25 jobs */ { printf("Getting a new job\n"); /*simulates a new job created */ jobInfo[i] = i + 100; /* simulates making data */ pthread_mutex_lock(&m); jobAvail++; pthread_cond_signal(&cv); pthread_mutex_unlock(&m); /* new job available */ } /* Help others finish */ /* (some might be blocked on the pthread_cond_wait call) */ while ( j1 != 0 || j2 != 0 || j3 != 0 ) { pthread_mutex_lock(&m); pthread_cond_signal(&cv); pthread_mutex_unlock(&m); sleep(1); } pthread_mutex_destroy(&m); pthread_cond_destroy(&cv); exit(0); }

  23. Signal Management

  24. Signal Management Example (1 of 2) /* sigmgmt.c */ #include <pthread.h> #include <signal.h> void *threadfunc(void * notused) { struct sigset_t set, oset; sigemptyset(&set); sigaddset(&set, SIGQUIT); sigthreadmask(SIG_BLOCK, &set, NULL); for(;;); /* simulate action */ } void * sigwaiter_thread(void *notused) { int sig; int ret; struct sigset_t set, oset; sigemptyset(&set); sigaddset(&set, SIGQUIT); sigthreadmask(SIG_BLOCK, &set, NULL); for(;;) { sigwait(&set,&sig); printf("sigwait() returned signal = %d\n", sig); } }

  25. Signal Management Example (2 of 2) main() { pthread_t waiterthd, thd; int status; struct sigset_t set, oset; struct sigaction mysig; pthread_attr_t attr; /* Block the signals. */ sigemptyset(&set); sigaddset(&set, SIGQUIT); sigthreadmask(SIG_BLOCK, &set, NULL); pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETATCHED); pthread_create(&waiterthd, &attr, sigwaiter_thread, NULL); pthread_create(&thd, &attr, threadfunc, NULL); sleep(2); pthread_join(thd, (void **)&status); printf("Main- check-\n"); }

  26. Cancellation Choices

  27. Cancellation Points

  28. Cancellation Cleanup

  29. Cancellation Example (1 of 2) /* pushpop.c */ #include <pthread.h> pthread_mutex_t m; void cleanup_m(void * m) { printf("In cleanup_m handler.\n"); pthread_mutex_unlock((pthread_mutex_t *)m); } void * thread_starter(void * notused) { printf("In thd1.\n"); pthread_mutex_lock(&m); pthread_cleanup_push(cleanup_m, (void *)&m); sleep(1); pthread_testcancel(); /* Cancelation point */ printf("If I reached here, I didn't get canceled.\n"); pthread_mutex_unlock(&m); pthread_cleanup_pop(0); pthread_exit(NULL); }

  30. Cancellation Example (2 of 2) main() { pthread_t thd1; pthread_mutex_init(&m, NULL); pthread_create(&thd1, NULL, thread_starter, NULL); pthread_cancel(thd1); pthread_mutex_destroy(&m); pthread_exit(NULL); }

  31. Scheduling

  32. Scheduling Example (1 of 2) /* thrdsched.c */ #include <pthread.h> void *func1( void *notused) { int priority; struct sched_param sched; pthread_getschedparam(pthread_self(), &priority, &sched); printf("Child thread policy is %d and priority is %d\n", sched.sched_policy, sched.sched_priority); }

  33. Scheduling Example (2 of 2) main() { struct sched_param sched; pthread_attr_t attr; pthread_t thd; printf("Legend:\nPolicy 0 is SCHED_OTHER.\n"); printf("Policy 1 is SCHED_FIFO.\n"); printf("Policy 2 is SCHED_RR.\n\n"); pthread_create( &thd, NULL, func1, NULL); sleep(1); printf("Changing policy of child thread to RR\n"); printf("Changing priority of child thread to 80\n"); pthread_attr_init(&attr); sched.sched_policy = SCHED_RR; sched.sched_priority= 80; pthread_attr_setschedparam(&attr, &sched); pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); pthread_create( &thd, &attr, func1, NULL); pthread_exit(NULL); }

  34. Once Only Initialization • Initialize variable=PTHREAD_ONCE_INIT • Even if many threads call pthread_once(&ariable,routine). • Routine() is called only once. pthread_once(&variable, routine) • is equivalent to: if(variable equals PTHREAD_ONCE_INIT) { routine() change variable }

  35. Once Only Example (1 of 2) /* once.c */ #include <pthread.h> #include <unistd.h> pthread_t thd[2]; static pthread_once_t once = PTHREAD_ONCE_INIT; void init() { pthread_t self; /* Do your initializations here */ /* Check which thread is here */ self = pthread_self(); if(pthread_equal(self,thd[0])) printf("init() - invoked by Thread 1\n"); if(pthread_equal(self,thd[1])) printf("init() - invoked by Thread 2\n"); }

  36. Once Only Example (2 of 2) void * func(void *arg) { pthread_t self; /* init() should be called only once */ (void)pthread_once(&once, init); self = pthread_self(); if(pthread_equal(self,thd[0])) printf("In Thread 1\n"); if(pthread_equal(self,thd[1])) printf("In Thread 2\n"); pthread_exit((void *)1); } main() { pthread_create(&thd[0], NULL, func, 0); pthread_create(&thd[1], NULL, func, 0); pthread_exit( (void **)1); }

  37. Forking considerations

  38. Forking Example (1 of 2) /* atfork.c */ #include <pthread.h> #include <sys/types.h> pthread_mutex_t m; void prefork_prepare(void) { printf("prepare\n"); pthread_mutex_lock(&m); } void postfork_parent(void) { printf("parent\n"); pthread_mutex_unlock(&m); } void postfork_child(void) { printf("Child\n"); pthread_mutex_unlock(&m); } void * func(void * arg) { pthread_mutex_lock(&m); sleep(1); printf("In func before unlock\n"); pthread_mutex_unlock(&m); pthread_exit(NULL); }

  39. Forking Example (2 of 2) void * func(void *arg) { pthread_t self; /* init() should be called only once */ (void)pthread_once(&once, init); self = pthread_self(); if(pthread_equal(self,thd[0])) printf("In Thread 1\n"); if(pthread_equal(self,thd[1])) printf("In Thread 2\n"); pthread_exit((void *)1); } main() { pthread_create(&thd[0], NULL, func, 0); pthread_create(&thd[1], NULL, func, 0); pthread_exit( (void **)1); }

More Related