共要賣票20張,由命令行輸入窗口數(shù),由線程模擬窗口。每賣掉一張票,屏幕顯示由幾號窗口所賣,一并顯示剩余票數(shù)
思路由于票數(shù) ticket_cnt 是全局變量,因此每當一個線程將其減一(賣出一張票),并將其顯示,應(yīng)該被封裝為一個原子操作。因為線程是并發(fā)執(zhí)行的,可能當前線程將ticket_cnt減1后還沒有來得及顯示此時的剩余票數(shù)ticket_cnt,ticket_cnt已經(jīng)被另一個線程減一了。此處通過互斥鎖實現(xiàn)互斥。
函數(shù)原型創(chuàng)建線程:
NAME pthread_create - create a new threadSYNOPSIS #include <pthread.h> int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg); Compile and link with -pthread.
回收線程資源,該函數(shù)為阻塞函數(shù)。
NAME pthread_join - join with a terminated threadSYNOPSIS #include <pthread.h> int pthread_join(pthread_t thread, void **retval); Compile and link with -pthread.DESCRipTION The pthread_join() function waits for the thread specified by thread to terminate. If that thread has already termi- nated, then pthread_join() returns immediately. The thread specified by thread must be joinable. If retval is not NULL, then pthread_join() copies the exit status of the target thread (i.e., the value that the tar- get thread supplied to pthread_exit(3)) into the location pointed to by *retval. If the target thread was canceled, then PTHREAD_CANCELED is placed in *retval. If multiple threads simultaneously try to join with the same thread, the results are undefined. If the thread calling pthread_join() is canceled, then the target thread will remain joinable (i.e., it will not be detached).RETURN VALUE On success, pthread_join() returns 0; on error, it returns an error number.
解鎖開鎖
NAME pthread_mutex_lock pthread_mutex_unlock - lock and unlock a mutexSYNOPSIS #include <pthread.h> int pthread_mutex_lock(pthread_mutex_t *mutex); int pthread_mutex_unlock(pthread_mutex_t *mutex);
初始化鎖,銷毀鎖
NAME pthread_mutex_destroy, pthread_mutex_init - destroy and initialize a mutexSYNOPSIS #include <pthread.h> int pthread_mutex_destroy(pthread_mutex_t *mutex); int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);代碼
/************************************************************************* > File Name: ticket.c > Author: KrisChou > Mail:zhoujx0219@163.com > Created Time: Mon 25 Aug 2014 07:40:38 PM CST ************************************************************************/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <pthread.h>int ticket_cnt = 20; /* 共有20張票 */typedef struct tag{ int s_id; pthread_mutex_t *s_p;}DATA,*pDATA;void* handler(void *arg ){ int id = ((pDATA)arg)->s_id; pthread_mutex_t *p_mutex = ((pDATA)arg)-> s_p; PRintf("a window on !: %d /n", id); while(1) { pthread_mutex_lock(p_mutex); if(ticket_cnt == 0) { printf("ticket out! /n"); pthread_mutex_unlock(p_mutex); free((pDATA)arg); return (void*)0; } --ticket_cnt; sleep(rand()%3 + 1); printf("window: %d : a ticket sold. left : %d /n", id,ticket_cnt ); pthread_mutex_unlock(p_mutex); sleep(rand() % 3 + 1); /* 如果不sleep,鎖會一直被這個執(zhí)行完的線程所占據(jù) */ }}int main(int argc, char *argv[]){ srand(getpid()); pthread_mutex_t mutex; pthread_mutex_init(&mutex, NULL); int thd_cnt = atoi(argv[1]); /* 從命令行輸入賣票窗口數(shù) */ pthread_t *tds = (pthread_t*)calloc(thd_cnt,sizeof(pthread_t)); int index; for(index = 0; index < thd_cnt; index++ ) { pDATA p = (pDATA)calloc(1,sizeof(DATA)); p->s_id = index; p->s_p = &mutex; pthread_create(tds + index , NULL,handler,(void*)p); } printf("joining.../n"); for(index = 0; index < thd_cnt; index++) { pthread_join(tds[index],NULL); } pthread_mutex_destroy(&mutex); return 0;}編譯運行:
[purple@localhost review]$ gcc ticket.c -lpthread[purple@localhost review]$ ./a.out 5joining...a window on !: 2a window on !: 3a window on !: 4a window on !: 1a window on !: 0window: 2 : a ticket sold. left : 19window: 3 : a ticket sold. left : 18window: 4 : a ticket sold. left : 17window: 1 : a ticket sold. left : 16window: 0 : a ticket sold. left : 15window: 2 : a ticket sold. left : 14window: 3 : a ticket sold. left : 13window: 4 : a ticket sold. left : 12window: 1 : a ticket sold. left : 11window: 0 : a ticket sold. left : 10window: 2 : a ticket sold. left : 9window: 3 : a ticket sold. left : 8window: 4 : a ticket sold. left : 7window: 1 : a ticket sold. left : 6window: 0 : a ticket sold. left : 5window: 2 : a ticket sold. left : 4window: 3 : a ticket sold. left : 3window: 4 : a ticket sold. left : 2window: 1 : a ticket sold. left : 1window: 0 : a ticket sold. left : 0ticket out!ticket out!ticket out!ticket out!ticket out!干貨
如果有一個整型參數(shù) a 需要在創(chuàng)建線程時將其傳遞給線程,那么以下兩種傳值方式,實際上是由區(qū)別的。來看代碼:
方式1:
void* handler(void *arg){ int val=*(int*)arg; printf("from main: %d/n",val); pthread_exit((void*)"hello world");}int main(){ pthread_t thd; int a=12345; pthread_create(&thd,NULL,handler,(void*)&a); printf("thd: %x/n",thd); pthread_join(thd,(void*)&ret); return 0;}方式2:
void* handler(void *arg){ int val=(int)arg; printf("from main: %d/n",val); pthread_exit((void*)"hello world");}int main(){ pthread_t thd; int a=12345; pthread_create(&thd,NULL,handler,(void*)a); printf("thd: %x/n",thd); pthread_join(thd,(void*)&ret); return 0;}對于方式1,傳給handler的參數(shù)是a的地址,如果a的值之后在主線程里會發(fā)生變化,那么傳給handler的數(shù)值a可能就不是原來我們想傳的那個了。
而對于方式2,由于是值傳遞,我們當時想傳什么,傳到handler中的就一定是什么。
由此可見,雖然方式1節(jié)省了存儲空間,但是同樣也容易發(fā)生錯誤。
新聞熱點
疑難解答
圖片精選