線程就是運行在一個進程上下文中的邏輯流,通常來講,程序是由每一個進程中的單一線程來組成的。可是,咱們實際上也能夠編寫一個進程裏同時運行多個線程的程序,線程是由內核調度的,從進程間通訊角度來看,一個給定進程內的全部線程共享一樣的全局變量。每一個線程具備獨立的線程上下文,包括一個惟一的整數線程ID,棧,棧指針,程序計數器,通用目的寄存器和條件碼。全部運行在一個進程中的線程共享該進程的整個虛擬地址空間。基於線程的邏輯流結合了基於進程和基於IO多路複用的流的特性,同進程同樣,線程有內核自動調度,而且內核經過一個整數ID來識別線程,同基於多路IO複用同樣,多個線程運行在單一進程的上下文之中,所以共享整個進程的虛擬地址空間,包括代碼、數據、堆和共享庫以及打開的文件。 服務器
每一個進程一開始都是由單一主線程構成的,在某一時刻,主線程建立一個對等線程,從這個時間點開始,兩個線程就開始併發地運行。最後,由於主線程執行一個慢速系統調用,例如read函數或者sleep函數,線程就會被內核掛起,控制就會經過上下文切換傳遞到對等線程。對等線程就這樣交替執行,以此類推。 多線程
//本程序是基於多線程的併發服務器 //爲了不賦值語句在accept以後才完成的,那麼對等線程中的局部變量connfd就獲得下一次鏈接的描述符值,不幸的是,兩個線程在同一個描述符上執行輸入和輸出 //爲了不這種致命競爭,必須將每一個accept返回的已鏈接符分配到它本身的動態分配的存儲器塊 #include "csapp.h" void echo(int connfd) { int n; char buf[MAXLINE]; rio_t rio; rio_readinitb(&rio,connfd); //帶緩衝的讀取函數 while((n=rio_readlineb(&rio,buf,MAXLINE))>0) { //向鏈接符寫入內容 printf("server received %d bytes \n",n); rio_writen(connfd,buf,n); } } void *thread(void *vargp); //線程函數聲明 //主函數入口 int main(int argc,char **argv) { int listenfd,*connfd,port; //監聽描述符,鏈接符,端口號 socklen_t clientlen=sizeof(struct sockaddr_in); //客戶端地址長度 struct sockaddr_in clientaddr; //新建客戶端地址 pthread_t tid; //線程id if(argc!=2) { fprintf(stderr,"usage :%s <port>\n",argv[0]); //提示執行格式 exit(0); //正常退出主程序,主進程 } port=atoi(argv[1]); //把端口號轉成整型 listenfd=open_listenfd(port); //打開監聽端口號 while(1) { //無限循環,等待接受請求 connfd=malloc(sizeof(int)); //動態分配內存給鏈接描述符,這是爲了不兩個線程在同一個描述符上輸入輸出,致使兩個線程在同一個描述符上的不正當競爭 *connfd=accept(listenfd,(SA *)&clientaddr,&clientlen); //接受請求,已鏈接描述符 pthread_create(&tid,NULL,thread,connfd); //新建線程,而且傳遞參數connfdp進入線程 } } void *thread(void *vargp) { int connfd=*((int *)vargp);//接受參數 pthread_detach(pthread_self()); //分離線程,使得它不能被其餘線程回收或殺死的,它的存儲器資源在它終止時由系統自動釋放 free(vargp); //釋放參數存儲空間 echo(connfd); //迴應客戶端 close(connfd); //關閉已鏈接描述符,這裏不用在主線程中關閉,由於線程共享同一虛擬地址空間,此處關閉便可 return NULL;//線程結束 }
上面的多線程編譯時,要加上-pthread參數,程序運行以下: 併發
zzw@zzw-ThinkPad-Edge-E430c:~$ telnet localhost 9999 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. hello hello
zzw@zzw-ThinkPad-Edge-E430c:~/doc_main/CProgram/Concurrency$ ./echoservert.o 9999 server received 7 bytes