轉自:http://www.cnblogs.com/coder2012/archive/2013/03/31/2991785.html
線程的優點:
- 減少系統調度開銷,不占有獨立的資源,切換速度快,執行效率高。
- 線程間通信方便,可共享資源。
- 改善程序設計結構,功能復雜的進程可以分為多個獨立的線程分別執行,模塊性更強。
線程分為:用戶態線程和核心態線程。
用戶態的多線程程序在運行時不許要特定的內核支持,同一個進程的線程之間進行切換時,不需要調用系統調用。
核心態線程的實現方法允許不同進程中的的線程按照相同的調度方法進行調度,有利於發揮多處理器的並發優勢。
線程創建:
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void*),void *arg); //thread 指向線程標識符的指針,使用這個標識符來引用新線程 //attr 設置線程屬性,設為NULL則生成默認屬性的線程 //start_routine 線程運行函數的起始位置 //arg 線程運行函數的參數
線程終止:
1.通過線程自身結束 void pthread_exit(void *rval_ptr); //rval_ptr是函數的返回代碼,相當於線程的退出碼 2.通過同一進程的其他線程來結束 int pthread_cancel(pthread_t tid); //tid是要結束線程的標識符
下面的函數用於阻塞等待一個線程的結束
int pthread_join(pthread_t thread, void **return_ptr)
//創建線程,輸出當前系統的時間 #include<stdio.h> #include<stdlib.h> #include<time.h> #include<unistd.h> #include<pthread.h> void print_currentTime(void) { time_t ct; ct=time(NULL); //ctime:將秒數轉換成字符串 printf("current time is : '%s'",ctime(&ct)); pthread_exit("Time thread finished!\n"); } int main() { int ret; void *thread_result; pthread_t new_thread; ret=pthread_create(&new_thread,NULL,(void*)print_currentTime,NULL); if(ret!=0){ perror("thread creation failed!\n"); exit(EXIT_FAILURE); } printf("waiting for new thread....\n"); ret=pthread_join(new_thread,&thread_result); if(ret!=0){ perror("thread join failed!\n"); exit(EXIT_FAILURE); } printf("thread joined, returned: %s\n",(char*)thread_result); return 0; } //編譯時候注意: gcc thread_date.c -o thread_date -lpthread
線程屬性:
線程屬性主要包括分離屬性,綁定屬性,調度屬性,堆棧屬性,繼承屬性等,結構為pthread_attr_t。
屬性設置函數:
int pthread_attr_init(pthread_attr_t *attr) //attr是指向屬性結構的指針 //注意:此函數必須在調用pthread_creater()函數之前調用
這里提到了一個概念“輕進程(Light Weight Process, LWP)”,位於用戶層與系統層之間的內核線程。系統對線程資源的分配以及對線程的控制是通過輕進程來實現的,一個輕進程可以控制一個或多個線程。
獲取線程綁定狀態函數:
int pthread_attr_getscope(pthread_attr_t *attr, int *scope) //scope返回綁定屬性的狀態
設置線程綁定屬性函數:
int pthread_attr_setscope(pthread_attr_t* attr, int scope) //scope是要綁定的類型
獲得線程優先級函數:
int pthread_attr_getschedparam(pthread_attr_t *attr, const struct sched_param *param) //param中存放線程的調度參數信息
設置線程優先級函數:
int pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param)
獲取調度策略函數:
int pthread_attr_getschedpolicy(pthread_attr *attr, int *policy) //調度策略存放在policy中
設置調度策略函數:
int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
獲取並發級別函數:
int pthread_getconcurrency(void)
設置並發級別函數:
int pthread_setconcurrency(int new_level)
多線程同步技術:
線程同步機制主要有:互斥量,信號量,條件變量,讀寫鎖等。
互斥量:
數據類型為pthread_mytex_t,主要函數:
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr); int pthread_mutex_lock(pthread_mutex_t *mutex); //阻塞調用 int pthread_mutex_trylock(pthread_mutex_t *mutex); //非阻塞調用 int pthread_mutex_unlock(pthread_mutex_t *mutex); int pthread_mutex_destroy(pthread_mutex_t *mutex); //mutex是定義的pthread_mutex_t的指針,mutex_attr是互斥量的屬性結構
例子:
#include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<pthread.h> #include<string.h> pthread_mutex_t mutex; int count=0; char msg_buf[64]; void setMsg_Func(void) { while(count>0){ pthread_mutex_lock(&mutex); memset(msg_buf,0,64); sprintf(msg_buf,"count=%d.\n",count--); pthread_mutex_unlock(&mutex); srand((int)time(0)); sleep(rand()%3); } pthread_exit(0); } void printMsg_Func(void) { while(count>=0){ pthread_mutex_lock(&mutex); printf("%s",msg_buf); pthread_mutex_unlock(&mutex); if(0==count) break; srand((int)time(0)); sleep(rand()%3); } } int main() { int ret; pthread_t set_thread; count=4; pthread_mutex_init(&mutex,NULL); ret=pthread_create(&set_thread,NULL,(void*)&setMsg_Func,NULL); if(ret!=0){ perror("thread creation failed!\n"); exit(EXIT_FAILURE); } printMsg_Func(); ret=pthread_join(set_thread,NULL); if(ret!=0){ perror("thread creation failed!\n"); exit(EXIT_FAILURE); } printf("Finished!\n"); pthread_mutex_destroy(&mutex); return 0; }
但是要注意,如果使用互斥量過程中,如果兩個線程試圖同時占用兩個資源,並鎖定,可能造成死鎖。
條件變量:
只使用互斥量很可能造成死鎖,為此可以加入條件變量。條件變量允許線程阻塞和等待另一個線程發送信號,使用條件變量可以以原子方式阻塞線程,直到滿足某個條件為止。
互斥量主要用來保證對臨界區的互斥進入,而條件變量則用於線程的阻塞等待。
int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr); //創建條件變量 int pthread_cond_signal(pthread_cond_t *cond); //用來釋放被阻塞在條件變量cond上的進程 int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex); //使線程阻塞 int pthread_cond_broadcast(pthread_cond_t *cond); //用來喚醒所有阻塞在條件變量cond上的線程 int pthread_cond_timewait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime); //使線程阻塞,與wait不同,它經過abstime時間后,無論條件是否滿足,都會釋放 int pthread_cond_destroy(pthread_cond_t *cond); //cond是一個指向結構pthread_cond_t的指針 //cond_attr是條件變量的屬性結構指針
例子:
//創建兩個線程,偶數時進程1給變量加1,奇數時進程2給變量加1 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <pthread.h> #define MAX_COUNT 9 pthread_mutex_t mutex; pthread_cond_t cond; int count=0; void addCount_odd_Func(void) { pthread_mutex_lock(&mutex); while(count<MAX_COUNT){ if(count%2==1){ count++; printf("addcout_odd_Func():count=%d.\n",count); pthread_cond_signal(&cond); } else pthread_cond_wait(&cond,&mutex); } pthread_mutex_unlock(&mutex); } void addCount_even_Func(void) { pthread_mutex_lock(&mutex); while(count<MAX_COUNT){ if(count%2==0){ count++; printf("addCount_even_Func:count=%d.\n",count); pthread_cond_signal(&cond); } else pthread_cond_wait(&cond,&mutex); } pthread_mutex_unlock(&mutex); } int main(int argc, char **argv) { int ret; pthread_t odd_thread,even_thread; pthread_attr_t thread_attr; count=0; pthread_mutex_init(&mutex,NULL); pthread_cond_init(&cond,NULL); ret=pthread_attr_init(&thread_attr); if(ret!=0){ perror("attribute creation failed!"); exit(EXIT_FAILURE); } pthread_attr_setdetachstate(&thread_attr,PTHREAD_CREATE_DETACHED); ret=pthread_create(&odd_thread,&thread_attr,(void*)&addCount_odd_Func,NULL); if(ret!=0){ perror("thread creation failed!"); exit(EXIT_FAILURE); } ret=pthread_create(&even_thread,&thread_attr,(void*)&addCount_even_Func,NULL); if(ret!=0){ perror("thread creation failed!"); exit(EXIT_FAILURE); } while(count<MAX_COUNT); printf("Finished!"); pthread_cond_destroy(&cond); pthread_mutex_destroy(&mutex); return 0; }