介紹linux執行緒的基本概念,執行緒間的互斥和同步機制,分析了linuxpthread庫的api函式,並結合乙個例子闡述多執行緒程式設計的核心技術,最後總結出多執行緒程式設計應注意的事項。
中圖分類號:tp316 文獻標識碼:a
1.引言
目前,許多流行的多工作業系統都提供執行緒機制,執行緒就是程式中的單個順序控制流。利用多執行緒進行程式設計,就是將乙個程式(程序)的任務劃分為執行的多個部分(執行緒) ,每乙個執行緒為乙個順序的單控制流,而所有執行緒都是併發執行的,這樣,多執行緒程式就可以實現平行計算,高效利用多處理器。執行緒可分為使用者級執行緒和核心級執行緒兩種基本型別。使用者級執行緒不需要核心支援,可以在使用者程式中實現,執行緒排程、同步與互斥都需要使用者程式自己完成。核心級執行緒需要核心參與,由核心完成執行緒排程並提供相應的系統呼叫,使用者程式可以通過這些介面函式對執行緒進行一定的控制和管理。linux作業系統提供了linuxthreads庫,它是符合posix1003.1c標準的核心級多執行緒函式庫。在linuxthreads庫中提供了一些多執行緒程式設計的關鍵函式,在多執行緒程式設計時應包括pthread.**件。
2.linuxthread中的關鍵庫函式
2.1執行緒的建立和終止
int pthread_create(pthread_t * pthread,const pthread_attr_t *attr,void *(*start_routine(*void)),void *arg);呼叫此函式可以建立乙個新的執行緒,新執行緒建立後執行start_routine 指定的程式。其中引數attr是使用者希望建立執行緒的屬性,當為null時表示以預設的屬性建立執行緒。arg是向start_routine 傳遞的引數。當成功建立乙個新的執行緒時,系統會自動為新執行緒分配乙個執行緒id號,並通過pthread 返回給呼叫者。
void pthread_exit(void *value_ptr);呼叫該函式可以退出執行緒,引數value_ptr是乙個指向返回狀態值的指標。
2.2執行緒控制函式
int pthread_join (pthread- t thread , void * *status);這個函式的作用是等待乙個執行緒的結束。呼叫pthread_join()的執行緒將被掛起直到執行緒id為引數thread 指定的執行緒終止。
int pthread_detach(pthread_t pthread);引數pthread代表的執行緒一旦終止,立即釋放調該執行緒占有的所有資源。
2.3執行緒間的互斥
互斥量和臨界區類似,只有擁有互斥量的執行緒才具有訪問資源的許可權,由於互斥物件只有乙個,這就決定了任何情況下共享資源(**或變數)都不會被多個執行緒同時訪問。使用互斥不僅能夠在同一應用程式的不同執行緒中實現資源的安全共享,而且可以在不同應用程式的執行緒之間實現對資源的安全共享。linux中通過pthread_mutex_t來定義互斥體機制完成互斥操作。具體的操作函式如下
pthread_mutex_init(pthread_mutex_t *mutex,const pthread_mutexattr_t *attr);初使化乙個互斥體變數mutex,引數attr表示按照attr屬性建立互斥體變數mutex,如果引數attr為null,則以預設的方式建立。
pthread_mutex_lock(pthread_mutex_t *mutex);給乙個互斥體變數上鎖,如果mutex指定的互斥體已經被鎖住,則呼叫執行緒將被阻塞直到擁有mutex的執行緒對mutex解鎖為止。
pthread_mutex_unlock(pthread_mutex_t *mutex);對引數mutex指定的互斥體變數解鎖。
2.4執行緒間的同步
同步就是執行緒等待某乙個事件的發生,當等待的事件發生時,被等待的執行緒和事件一起繼續執行。如果等待的事件未到達則掛起。在linux作業系統中是通過條件變數來實現同步的。
pthread_cond_init(pthread_cond_t *cond,const pthread_cond_t *attr);這個函式按引數attr指定的屬性初使化乙個條件變數cond。
pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex);等待乙個事件(條件變數)的發生,發出呼叫的執行緒自動阻塞,直到相應的條件變數被置1。等待狀態的執行緒不占用cpu時間。
pthread_cond_signal(pthread_cond_t *cond);解除乙個等待引數cond指定的條件變數的執行緒的阻塞狀態。
3.多執行緒程式設計的應用例項。
在這裡利用多執行緒技術實現生產者和消費者問題,生產者執行緒向一緩衝區中寫資料,消費者執行緒從緩衝區中讀取資料,由於生產者執行緒和消費者執行緒共享同一緩衝區,為了正確讀寫資料,在使用緩衝佇列時必須保持互斥。生產者執行緒和消費者執行緒必須滿足:生產者寫入緩衝區的數目不能超過緩衝區容量,消費者讀取的數目不能超過生產者寫入的數目。在程式中使用了乙個小技巧來判斷緩衝區是空還是滿。在初始化時讀指標和寫指標為0;如果讀指標等於寫指標,則緩衝區是空的;如果(寫指標+ 1) % n 等於讀指標,則緩衝區是滿的,%表示取餘數,這時實際上有乙個單元空出未用。下面是完整的程式段和注釋。
#include
#include
#define buffer_size 8
struct prodcons ;
void init(struct prodcons * b)
void put(struct prodcons* b,int data)
b->buffer[b->writepos]=data;
b->writepos++;
if(b->writepos >= buffer_size)
b->writepos=0;
pthread_cond_signal(&b->notempty);
pthread_mutex_unlock(&b->lock);
}int get(struct prodcons *b)
data = b->buffer[b->readpos];
b->readpos++;
if(b->readpos >= buffer_size)
b->readpos=0;
pthread_cond_signal(&b->notfull);
pthread_mutex_unlock(&b->lock);
return data;
}#define over (-1)
struct prodcons buffer;
void *producer(void *data)
put(&buffer, over);
return null;
}void *consumer(void * data)
return null;
}int main(void)
上面的例子中,生產者負責將1到1000的整數寫入緩衝區,而消費者負責從同乙個緩衝區中讀取寫入的整數並列印出來。因為生產者和消費者是兩個同時執行的執行緒,並且要使用同乙個緩衝區進行資料交換,因此必須利用一種機制進行同步。通過上面的例子我們可以看到,多執行緒的最大好處是,除堆疊之外,幾乎所有的資料均是共享的,因此執行緒間的通訊效率很高;缺點:因為共享所有資料,從而非常容易導致執行緒之間互相破壞資料,這一點在程式設計時必須注意。
4.結束語
linux中基於posix標準的很好的支援了多執行緒技術,它減少了程式併發執行時的系統開銷,提高了計算機的工作效率。在具體程式設計過程中要了解執行緒的間的關係,還要考慮共享資料的保護,在互斥和同步機制下保證**的高效執行,程式編譯時用gcc -d –reentrant -libpthread.xx.so filename.c編譯。
Linux多執行緒函式解析
linux多執行緒函式解析 linux多執行緒函式用得比較多的是下面的3個 pthread create pthread exit pthread join 它們都是在標頭檔案之中。編譯時需要加靜態庫 lpthread 下面是函式的說明 pthread create是unix環境建立執行緒函式 in...
Linux多執行緒函式解析
linux多執行緒函式解析 linux多執行緒函式用得比較多的是下面的3個 pthread create pthread exit pthread join 它們都是在標頭檔案之中。編譯時需要加靜態庫 lpthread 下面是函式的說明 pthread create是unix環境建立執行緒函式 in...
多執行緒細節解析
在學習完多執行緒後,分析一下一下兩種方法建立4個執行緒的不同之處!建立執行緒方法1 public static void main 建立執行緒方法2 public static void main 方法1和方法2都是建立了4個執行緒,類mythread實現了runnable介面 方法1是用for迴圈...