細談linux下的posix多線程編程

POSIX線程概述

定義:一個程序中的多個執行路線叫做線程,線程是一個進程內部的控制序列。所有的進程都至少有一個執行線程(初始線程)。初始線程隨進程的創建而創建,其他線程則需要通過顯式的函數調用來創建。

實現posix線程的主要函數。

①創建新線程

#include <pthread.h>

int pthread_create(
         pthread_t * thread,                 //返回指向線程標識符的指針
         pthread_attr * attr,                 //設置線程屬性
         void *(*func)(void*),               //新線程將啓動的函數的地址
         void * arg );                            //傳遞給新線程啓動函數的參數(注意類型的強制轉換)

說明:函數執行成功返回0,失敗返回錯誤碼。執行成功後,新線程將從設定的函數處開始執行,原線程則繼續執行。

 

②退出線程

#include <pthread.h>

void pthread_exit(void * ret);

說明:終止調用此函數的線程,並返回一個指向某對象的指針(ret)。注意,不能返回指向局部變量的指針。注意:在主線程中調用pthread_exit,進程將等待所有線程結束後才終止。


③合併線程

#include <pthread.h>

int pthread_join(pthread_t  thread, void **ret);

說明:等價於進程中用於收集子進程的wait()函數,thread 是要等待的線程(即通過pthread_creat函數返回的線程標識符),ret是一個二級指針,它指向一個指針,後者指向線程的返回值。函數執行成功時返回0,失敗時返回錯誤碼。pthread_join的功能是等待某線程結束,並收集其返回值。初始線程結束後(從main函數返回),整個進程即結束,導致進程內所有線程全部終止。在主線程中調用pthread_exit,進程將等待所有線程結束後才終止。

下面實現一個簡單的多線程編程的例子。

 

線程同步:

       線程體現了程序執行的併發性(並行:併發、同時),多個線程併發執行,且同一進程內部的多個線程可以共享除局部變量之外的所有變量。用信號量同步線程用於線程同步,有四個處理函數:

#include <semaphore.h>

sem_t是用於同步的信號量
//初始化信號量
int sem_init(sem_t *sem, int pshared, unsigned int val); 

pshared:信號量類型,如爲0,則爲當前進程獨享的信號量。
val:信號量的初始值。
//信號量減1
int sem_wait(sem_t *sem);
//信號量加1
int sem_post(sem_t *sem);
//銷燬信號量
int sem_destory(sem_t *sem)

 

下面的例子驗證了兩個線程是併發執行的,其中一個線程用於讀入用戶輸入的字符串,另一個線程用於統計字符串的長度。

 

線程互斥:

用互斥量同步線程互斥量允許程序員原子性的鎖住某對象,使得每次只有一個線程可以訪問它。

互斥量基本函數

#include <pthread.h>
//初始化互斥量
int pthread_mutex_init(pthread_mutex * mutex,const pthread_mutexattr_t * mutexattr);
//互斥量加鎖
int pthread_mutex_lock(pthread_mutex * mutex);
//互斥量解鎖
int pthread_mutex_unlock(pthread_mutex * mutex);
//銷燬互斥量
int pthread_mutex_destroy(pthread_mutex * mutex);

 

      程序需要仔細設計,避免死鎖。下面的例子驗證了兩個線程是併發執行的,其中一個線程用於讀入用戶輸入的字符串,另一個線程用於統計字符串的長度,線程在對共享區域(char str_buf[BUFFER_SIZE])操作時先對其加鎖,操作完畢後解鎖。

 

線程屬性:

創建線程時可以指定線程的屬性,需要首先創建一個屬性對象,然後用這個屬性對象作爲參數去創建線程。

#include <pthread.h>

int pthread_attr_init(pthread_attr_t *attr);

屬性舉例

如果不需要新創建的線程向主函數返回參數,也不需要初始線程等待新創建的線程執行結束,此時可以指定新線程的屬性爲分離屬性。

#include <pthread.h>

int pthread_attr_setdetachstate(
              pthread_attr_t* attr                 //屬性對象
              int detachstate  );                     //屬性值
PTHREAD_CREATE_DETACHED:分離線程,無需(嚴格來說是不可以)使用pthread_join()函數合併。 
PTHREAD_CREATE_JOINABLE:允許其他線程合併此線程。

 

 

線程取消:

線程可以終止另一個線程

#include <pthread.h>

int pthread_cancel(pthread_t  thread);

thread:需要取消的線程標識符,由pthread_creat()返回。

 

線程需要設置是否允許被其他線程終止,即設置自己的取消狀態

#include <pthread.h>

int pthread_setcancelstate(int state, int *oldstate);

state: PTHREAD_CANCEL_ENABLE:允許自身被其他線程取消。  PTHREAD_CANCEL_DISABLE:不允許被取消。

oldstate:返回先前的取消狀態。

 

線程還需要設置自己的取消類型

#include <pthread.h>

int pthread_setcanceltype(int type, int *oldtype);

type:

PTHREAD_CANCEL_ASYNCHRONOUS:接收到取消請求後立即取消。

PTHREAD_CANCEL_DEFERRED:接到取消請求後,一直等待到線程執行了下述函數才取消——pthread_join,pthread_cond_wait,pthread_cond_timedwait,pthread_testcancel,sem_wait,sigwait。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章