linux c 多(duo)線程編程實例
時間:2018-01-26 來(lai)源:未(wei)知
在主流的操作(zuo)系統中,多任務一般都提供(gong)了進程(cheng)(cheng)和線(xian)程(cheng)(cheng)兩種實現方(fang)式,進程(cheng)(cheng)享有(you)獨立(li)
的(de)進程空間,而線(xian)程相對于(yu)進程來說(shuo)是一(yi)種更加輕量級(ji)的(de)多(duo)任務并(bing)行,多(duo)線(xian)程之間一(yi)般都是共
享(xiang)所在進(jin)程的內存空間(jian)的。
Linux也(ye)不例外,雖然(ran)從內核的角度來看,線(xian)程體現(xian)為一(yi)種對進程的"克隆(long)"(clone),共
享進程(cheng)的(de)資源。但(dan)是(shi)在用戶空間提供(gong)了線程(cheng)管(guan)理(li)機制來(lai)實現(xian)對(dui)線程(cheng)的(de)管(guan)理(li),目(mu)前Linux中流行
的(de)(de)線(xian)(xian)程(cheng)機(ji)制為LinuxThreads,下面以(yi)一個(ge)多線(xian)(xian)程(cheng)編程(cheng)實例來介紹該線(xian)(xian)程(cheng)庫的(de)(de)編程(cheng)接口(kou):
示例1:線程的(de)創(chuang)建和退出,等待(dai)線程結束和獲取線程的(de)返回值
#include
#include
#include
/************************************************************
*線程函(han)數:線程運行(xing)執(zhi)行(xing)的函(han)數
*參數p:通用(yong)類型(xing)的(de)指針,啟動線(xian)程時(shi)傳(chuan)遞給線(xian)程函數的(de)參數
*返回值:通用類型指針,線程結束(shu)后啟動線程的(de)函(han)數可以獲(huo)取(qu)該值
*************************************************************/
void* task(void* p){
double r = *(double*)p;
printf("%lf\n",3.14*r*r);
}
void* task2(void* p){
static int sum = 0;
int i;
for(i=1;i<11;i++)
sum = sum+i;
return ∑
//pthread_exit(&sum);線程退出,和return等價(jia)
}
int main(){
pthread_t id1,id2;
double d = 1.0;
int* pi = NULL;
/*
*創(chuang)(chuang)建線程函數(shu),在主線程中調用該函數(shu)可以創(chuang)(chuang)建線程
*參數(shu)1:線程ID,ID由系(xi)統分配,該參數(shu)是一個傳出參數(shu),類型為(wei)pthread_t *
*參(can)數2:線程屬(shu)(shu)性,使用(yong)默(mo)認屬(shu)(shu)性給0即可,類型為pthread_attr_t *
*參(can)數3:線程函數,即線程運行時代碼,類型為void *(*)(void *)
*參數(shu)4:傳(chuan)遞給線程(cheng)函(han)數(shu)的參數(shu)
*/
pthread_create(&id1,0,task,&d);//計(ji)算圓(yuan)的面積
pthread_create(&id2,0,task2,0);//計(ji)算(suan)累加和
/*
*等待線(xian)程結(jie)束(shu)函數(shu),用于在(zai)一個線(xian)程中(zhong)等待另外一個線(xian)程結(jie)束(shu)
*參數1:要等待(dai)結束的線(xian)程的ID
*參(can)數2:結(jie)束線程的返(fan)回值的地址(由于是(shi)(shi)傳出(chu)參(can)數,所以是(shi)(shi)返(fan)回值的地址)
*/
pthread_join(id1,0);
pthread_join(id2,(void**)&pi);//pi=∑
printf("sum=%d\n",*pi);
return 0;
}
此外(wai),我們還可以設置線程的(de)屬(shu)性,下面介紹設置線程分離屬(shu)性的(de)代(dai)碼
示例2:設置線程的分離屬性
#include
#include
//線程函數
void* task(void* p){
int i;
for(i=0;i<50;i++){
printf("%d\n",i);
usleep(100000);//0.1秒(miao)
}
}
int main(){
pthread_t id;
pthread_create(&id,0,task,0);
/*
*將(jiang)線程(cheng)(cheng)設置為分離屬性,分離屬性的(de)線程(cheng)(cheng)一旦結束(shu),直接(jie)回收資(zi)源(yuan)
*因此當線(xian)程(cheng)(cheng)設置為分(fen)離(li)屬性后將無法再(zai)等待線(xian)程(cheng)(cheng)結(jie)束和(he)獲取線(xian)程(cheng)(cheng)的返回值
*參(can)數:設置分離(li)屬性的線程ID
*/
pthread_detach(id);//detach的(de)線(xian)程(cheng)join
//pthread_join(id,0);//無效
int i;
for(i=0;i<50;i++){
printf("main:%d\n",i);
usleep(100000);//0.1秒
}
}
由(you)于多(duo)線(xian)(xian)程(cheng)(cheng)(cheng)之間是共享(xiang)進程(cheng)(cheng)(cheng)資源的(de),所(suo)以多(duo)線(xian)(xian)程(cheng)(cheng)(cheng)編程(cheng)(cheng)(cheng)時(shi)需要對共享(xiang)資源的(de)訪(fang)問進行保護
包括互(hu)斥和同步,常(chang)用(yong)的(de)方式包括互(hu)斥鎖和信號量(liang)
示(shi)例(li)3:互斥鎖的使(shi)用
#include
#include
char* data[5];//定(ding)義一個(ge)長度是5字符串(chuan)數組
int size = 0;//定義了當前下標,也是人數
pthread_mutex_t lock;//1 聲明
void* task(void* p){
pthread_mutex_lock(&lock);//3 加(jia)鎖
data[size] = (char*)p; //4 訪問共享資(zi)源
usleep(10000); ++size;
pthread_mutex_unlock(&lock);//5 解(jie)鎖
}
int main(){
data[size] = "liubei"; size++;
pthread_mutex_init(&lock,0);//2 初始化
pthread_t id1,id2;
pthread_create(&id1,0,task,"zhangfei");
pthread_create(&id2,0,task,"guanyu");
pthread_join(id1,0);
pthread_join(id2,0);
pthread_mutex_destroy(&lock);//6 刪除
int i;
for(i=0;i
printf("%s\n",data[i]);
}
示例4:信號量的使用
#include
#include
#include
#include
sem_t sem; //1 分配
void* task(void* p){
int i = (int)p;
printf("第%d個線程申請連接\n",i);
sem_wait(&sem);//3 P操作(計數-1)
printf("第%d個(ge)線程申請(qing)成(cheng)功\n",i);
srand(time(0));//4 模擬訪問共(gong)享(xiang)資源
sleep(rand()%10);
printf("第%d個線程(cheng)釋放(fang)資源\n",i);
sem_post(&sem);//5 V操作(計數+1)
}
int main(){
sem_init(&sem,0,10);//2 初始化(hua)
int i;
for(i=1;i<16;i++){
pthread_t id;
pthread_create(&id,0,task,(void*)i);
}
while(1);
}