POSIX線程—輕量級進程,線程調度是由核心發送器完成的,線程所消耗的系統資源比較少,相互連訊也比較容易。
多線程的優點:
1.資源消耗量少。我們知道,在Linux系統下,啟動一個新的進程必須分配給它獨立的地址空間,建立眾多的資料表來維護它的程式碼片段、堆棧段和資料區段,這是一種"昂貴"的多任務工作方式。而運行於一個進程中的多個線程,它們彼此之間使用相同的地址空間,共用大部分資料,啟動一個線程所花費的空間遠遠小於啟動一個進程所花費的空間,而且,線程間彼此切換所需的時間也遠遠小於進程間切換所需要的時間。據統計,總的說來,一個進程的開銷大約是一個線程開銷的30倍左右,當然,在具體的系統上,這個資料可能會有較大的區別。
2.通訊方便。對不同進程來說,它們具有獨立的資料空間,要進行資料的傳遞只能通過通訊的方式進行,這種方式不僅費時,而且很不方便。線程則不然,由於同一進程下的線程之間共用資料空間,所以一個線程的資料可以直接為其它線程所用,這不僅快捷,而且方便。當然,資料的共用也帶來其他一些問題,有的變數不能同時被兩個線程所修改,有的子程式中聲明為static的資料更有可能給多線程程式帶來災難性的打擊,這些正是編寫多線程程式時最需要注意的地方。
應用多進程的應用程式具有以下優點:
1) 提高應用程式響應。這對圖形介面的程式尤其有意義,當一個操作耗時很長時,整個系統都會等待這個操作,此時程式不會響應鍵盤、滑鼠、菜單的操作,而使用多線程技術,將耗時間長度的操作(time consuming)置於一個新的線程,可以避免這種尷尬的情況。
2) 使多CPU系統更加有效。作業系統會保證當線程數不大於CPU數目時,不同的線程運行於不同的CPU上。
3) 改善程式結構。一個既長又複雜的進程可以考慮分為多個線程,成為幾個獨立或半獨立的運行部分,這樣的程式會利於理解和修改。
好了,看了多線程的特點後,馬上練習一下
需要的標頭檔:pthread.h
線程標識符:pthread_t 在標頭檔/usr/include/bits/pthreadtypes.h中定義:
typedef unsigned long int pthread_t;
線程函數:
(1)extern int pthread_create __P ((pthread_t *__thread,// 指向線程標識符的指標
__const pthread_attr_t *__attr,// 設定線程屬性
void *(*__start_routine) (void *),//線程運行函數的起始地址
void *__arg));// 運行函數的參數
當建立線程成功時,函數返回0,若不為0則說明建立線程失敗,常見的錯誤傳回碼為EAGAIN和EINVAL。前者表示系統限制建立新的線程,例如線程數目過多了;後者表示第二個參數代表的線程屬性值非法。建立線程成功後,新建立的線程則運行參數三和參數四確定的函數,原來的線程則繼續運行下一行代碼。
(2)#include <pthread.h>
extern void pthread_exit __P ((void *__retval)) //函數的傳回碼
(3)等待一個線程的結束
oNormal" style="margin: 0cm 0cm 0pt 21pt; text-indent: 21pt; text-align: left;" align="left">#include <pthread.h>
extern int pthread_join __P ((pthread_t __th, //被等待的線程標識符
void **__thread_return));// 一個使用者定義的指標,它可以用來儲存被等待線程的傳回值
這個函數是一個線程阻塞的函數,調用它的函數將一直等待到被等待的線程結束為止,當函數返回時,被等待線程的資源被收回。
下面在linux環境下編寫 :
[cpp] view plaincopy
- /*threadtest.c*/
- #include <stdlib.h>
- #include <stdio.h>
- #include <pthread.h>
- #include <errno.h>
- /*聲明線程運行服務程式*/
- static void pthread_func_1 (void);
- static void pthread_func_2 (void);
-
- int main (void)
- {
- /*線程的標識符*/
- pthread_t pt_1 = 0;
- pthread_t pt_2 = 0;
- int ret = 0;
-
- /*分別建立線程1、2*/
- ret = pthread_create (&pt_1, //線程標識符指標
- NULL, //預設屬性
- (void *)pthread_func_1,//運行函數
- NULL); //無參數
- if (ret != 0)
- {
- perror ("pthread_1_create");
- }
-
- ret = pthread_create (&pt_2, //線程標識符指標
- NULL, //預設屬性
- (void *)pthread_func_2, //運行函數
- NULL); //無參數
- if (ret != 0)
- {
- perror ("pthread_2_create");
- }
- /*等待線程1、2的結束*/
- pthread_join (pt_1, NULL);
- pthread_join (pt_2, NULL);
- /*主線程退出*/
- printf ("main programme exit!/n");
- return 0;
- }
- /*線程1的服務程式*/
- static void pthread_func_1 (void)
- {
- int i = 0;
-
- for (; i < 6; i++)
- {
- printf ("This is pthread1!/n");
-
- /*i==2時退出,即迴圈3次*/
- if (i == 2)
- {
- pthread_exit (0);
- }
-
- sleep (1);
- }
- }
- /*線程2的服務程式*/
- static void pthread_func_2 (void)
- {
- int i = 0;
-
- for (; i < 3; i++)
- {
- printf ("This is pthread2!/n");
- }
-
- pthread_exit (0);
- }
編譯:
$ gcc threadtest.c -lpthread -o threadtest
運行:
$ ./threadtest
好,運行結果如下:
This is pthread1!
This is pthread2!
This is pthread2!
This is pthread2!
This is pthread1!
This is pthread1!
main programme exit!
上面例子很清楚地看出各個線程間的運行情況