一、線程的一般概念
線程可以看作是輕量級的進程,所有的程式都有一個主線程(main thread),主線程是進程的控制流程或執行線程。在多線程程式中,主線程可以建立一個或多個對等線程(peer thread),從這個時間點開始,這些線程就開始並發執行。主線程和對等線程的區別僅在於主線程總是進程中第一個啟動並執行線程。線程有兩個優點:資源消耗量少和方便的通訊機制。
二、線程的常用操作
(1)建立一個線程:pthread_create
int pthread_create(pthread_t *thread,pthread_attr_t *attr,void *(*start_routine)(void*),void *arg);
第一個參數為要建立的線程結構pthread_t,第二個參數為線程的相關屬性,第三個參數是該線程要執行的函數的指標,第四個則是傳遞給*start_routine的參數,可以自行選擇它的取值和用法。
pthread_create執行成功返回0,並把tid線程標識符存放到pthread_t結構中;否則返回一個非零值並設定errno。
(2)終止當前線程:pthread_exit
void pthread_exit(void *retval);
pthread_exit退出當前線程,退出之前將調用pthread_cleanup_push。它線上程的最上層函數的最後是被隱式調用的,這時可以 加一個retval參數顯式調用之,以供pthread_join參考。
(3)掛起當前線程:pthread_join
int pthread_join(pthread_t th,void **thread_return);
pthread_join把當前線程掛起直到指定的線程th終止,thread_return為th終止時的參數,如果沒有顯式指定,則為NULL。
(4)撤消一個線程:pthread_cancel
int pthread_cancel(pthread_t thread);
(5)等待線程的結束:pthread_join
int pthread_join(pthread_t th,void **thread_return);
調用這個函數的線程會掛起,直到等待的線程結束。這個函數的主要目的就是等待指定的線程結束,回收其記憶體資源。否則會浪費大量的記憶體資源。
三、線程資源互鎖
由於線程是共用資源的,所以互斥就顯得相當重要。互斥提供了對互斥對象上鎖的方法以獲得對此資源的獨佔,其它企圖對此互斥加鎖的線程則會被阻塞而掛起,直到對資源加鎖的線程解鎖為止。
在使用線程編程時,不必處處都使用互斥,否則會失去並發線程的意義,例如,在對使用只能串列單獨訪問的資源下方使用互斥。
互斥對象在pthead.h中定義為pthread_mutex_t。它的系統調用主要包括:
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutex_attr_t *mutexattr);
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);
pthread_mutex_init建立一個互斥對象,並用指定的屬性初始化這個互斥對象,初始化屬性包 括:PTHREAD_MUTEX_INITIALIZER建立快速互斥,這種互斥執行簡單的加鎖和解鎖,在加鎖後阻塞另一個要給它上鎖的線 程;PTHREAD_RECURSIVE_MUTEX_INITIALIZER建立遞迴互斥,這種互斥將給加鎖計數,解鎖時需要調用同樣次數的 pthread_mutex_unlock;
PTHREAD_ERRORCHECK_MUTEX_INITIALIZER建立檢錯互斥,這種互斥在被鎖上後會向試圖給它加鎖的線程返回一個EDEADLK錯誤碼而不阻塞。
pthread_mutex_lock和pthread_mutex_unlock則為加鎖和解鎖指定的互斥對 象,pthread_mutex_trylock和pthread_mutex_lock的不同是如果互斥對象已上鎖不會被阻塞而是返回一個EBUSY錯 誤代碼,pthread_mutex_destory析構指標mutex並釋放相關資源。這幾個調用成功都返回0,失敗返回一個非零的錯誤碼。
四、線程的維護
當建立完一個線程後,線程會根據CPU的時間分配就開始執行線程中的內容,為了線程能夠穩定的運行,即防止CPU阻塞等其他原因造成線程得不到CPU,而使得線程無法執行。這裡採用當運行到一定時間內,如果線程得不到執行,則撤銷先前的線程,重建立立。其一般操作如下:
(1)設定一個全域變數 g_SocketErr ;
(2)線上程中除了運行你要的功能以外,將 g_SocketErr=0;
(3)在main函數的while(1)中,
if (g_SocketErr>= 10) //若10次檢測都不正常,則關閉此線程,然後重新開啟此線程 { nErr = pthread_cancel(sock_tid); if (nErr != 0) { printf("cancel pthread_ipc error!\n"); } else { pthread_join(sock_tid, NULL); nErr = pthread_create(&sock_tid, NULL, ThreadSocket, NULL); //開啟環回socket線程 if (nErr != 0) { printf("creat socket err"); } else { g_SocketErr = 0; printf("Thread pthread_ipc create OK!\n"); } } } else { g_SocketErr++; }
好了,這次就總結到這裡。
參考:POSIX線程基本概念
pthread_cancel
http://blog.chinaunix.net/uid-14846899-id-2782352.html 這位同學整理的多線程讀書筆記整理的不錯。可以重點看下。
http://fanqiang.chinaunix.net/a4/b8/20010811/0905001105.html