第 11 章 多線程技術_第1頁
第 11 章 多線程技術_第2頁
第 11 章 多線程技術_第3頁
第 11 章 多線程技術_第4頁
第 11 章 多線程技術_第5頁
已閱讀5頁,還剩53頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

第11章多線程技術內容提要線程概述創建新進程線程控制線程取消線程同步多線程環境下的信號處理非線程安全函數的改造11.1線程概述線程概述

線程如同進程是系統可獨立調度的最小執行單元,它們僅在資源的使用方式上有所不同,進程間的用戶地址空間彼此獨立,然而,線程卻共享創建者進程的用戶地址空間等資源。引入線程的目的是為了減少對資源的消耗。創建新進程時,用戶可根據需求定制進程,,進程和線程為兩種最常見的新進程定制類型。進程與線程的關系棧(stack)文件描述符表棧(stack)代碼段(text)數據段(data)堆(heap)文件描述符表代碼段(text)數據段(data)堆(heap)線程線程棧(stack)進程多線程進程Linux線程的實現

由于線程誕生的時間較晚,早期的操作系統內核并不支持線程。1.用戶線程對不支持內核線程的操作系統,通過編程技巧,在一個進程中,可模擬出多條被稱為用戶線程的執行路徑,但用戶線程存在很多不足。2.內核線程內核線程通過修改內核代碼實現,目前,現代操作系統均支持內核線程。Linux線程的實現(續)1.LinuxThreads

LinuxThreads為POSIX線程庫的早期版本,自glibc2.4起不再使用,因受當時內核對線程支持不足的影響,LinuxThreads僅實現了POSIX線程的部分標準。2.NPTL

NPTL(NativePOSIXThreadsLibrary)屬于POSIX線程庫的現代版本,最早出現于glibc2.3.2,需內核2.6以上版本的支持。相較于LinuxThreads,NPTL更符合POSIX標準,在創建大量線程的情況下,具有更高的性能。應用編程接口分類API功能描述創建新進程clone創建新的進程線程屬性pthread_attr_init初始化線程屬性對象pthread_attr_destroy注銷線程屬性對象pthread_attr_getstack獲取線程棧的地址和大小pthread_attr_setstack設置線程棧的地址和大小pthread_attr_getdetachstate獲取線程的分離屬性pthread_attr_setdetachstate設置線程的分離屬性pthread_create創建線程pthread_join等待線程運行結束pthread_exit結束線程線程取消pthread_cancel向線程發送取消請求pthread_setcancelstate設置線程取消的狀態pthread_setcanceltype設置線程取消的類型pthread_testcancel測試線程的取消請求是否到達pthread_cleanup_push注冊線程清理函數應用編程接口線程同步互斥鎖pthread_mutex_init初始化互斥鎖pthread_mutex_destroy注銷互斥鎖pthread_mutex_lock申請獲得互斥鎖pthread_mutex_unlock釋放互斥鎖條件變量pthread_cond_init條件變量的初始化pthread_cond_wait等待條件變量pthread_cond_signal喚醒等待條件變量的線程pthread_cond_destroy注銷條件變量線程的信號處理pthread_kill向線程發送信號pthread_sigqueue向線程發送實時信號pthread_sigmask設置線程的信號掩碼非線程安全函數的安全化改造pthread_key_create創建線程持有數據關聯的鍵值pthread_key_delete刪除線程持有數據關聯的鍵值pthread_setspecific設置鍵關聯的線程持有數據pthread_getspecific獲取鍵關聯的線程持有數據11.2創建新進程創建新進程

自Linux內核2.0起,內核引入了clone系統調用,實現了對內核線程的初步支持,使用該系統調用可定制新的進程,其功能隨著Linux的發展不斷完善,glibc中的線程庫正是基于該系統調用構建。創建子進程頭文件

#define_GNU_SOURCE #include<sched.h>函數原型

int

clone(int(*fn)(void*),void*child_stack,intflags,void*arg…/*pid_t*ptid,void*newtls,pid_t*ctid*/);功能 創建新的進程。參數

fn:函數地址。

child_stack:棧地址。

flags:共享創建者進程的方式。

arg:指向傳遞的參數。返回值 成功返回線程的PID,失敗返回-1。11.3線程控制線程屬性

線程擁有諸多屬性,例如,棧和信號掩碼等,在創建線程前,根據特定的應用場景,應對其中部分屬性進行設置。1.初始化/注銷線程屬性對象。2.獲取/設置線程棧。3.獲取/設置線程的分離屬性。初始化/注銷線程屬性對象頭文件

#include<pthread.h>函數原型 int

pthread_attr_init(pthread_attr_t*attr);

int

pthread_attr_destroy(pthread_attr_t*attr);功能 初始化/注銷線程屬性對象。參數

attr:線程屬性對象。返回值 成功返回0,失敗返回-1非0設置線程棧頭文件

#include<pthread.h>函數原型

int

pthread_attr_getstack(pthread_attr_t*attr,void**addr,size_t*size);

int

pthread_attr_setstack(pthread_attr_t*attr,void*addr,size_tsize);功能 獲取/設置線程棧。參數

attr:線程屬性對象。

addr:線程棧地址。

size:線程棧大小。返回值 成功返回0,失敗返回非0。設置線程的分離屬性頭文件

#include<pthread.h>函數原型

int

pthread_attr_getdetachstate(pthread_attr_t*attr,int*state);

int

pthread_attr_setdetachstate(pthread_attr_t*attr,intstate);功能 獲取/設置線程的分離屬性。參數

attr:線程的屬性對象。

state:狀態標志。返回值 成功返回0,失敗返回非0。創建線程頭文件

#include<pthread.h>函數原型

int

pthread_create(pthread_t*tid,pthread_attr_t*attr,void*(*start)(void*),void*args);功能 創建線程。參數

tid:線程ID。

attr:線程的屬性。

start:線程執行的開始地址。

args:傳遞的參數。返回值

pthread_create函數成功返回0,失敗返回錯誤代碼。等待線程結束頭文件

#include<pthread.h>函數原型

int

pthread_join(pthread_t

tid,void**status)功能 等待線程結束。參數

tid:線程ID。

status:線程的返回狀態。返回值 成功返回0,失敗返回錯誤代碼。結束線程頭文件

#include<pthread.h>函數原型

voidpthread_exit(void*retval);功能 結束線程。參數

retval:返回狀態。返回值 無返回。11.4線程取消內容提要線程取消概述創建線程取消點線程的取消狀態和類型清理函數向線程發送取消請求線程取消概述

對于某些應用,有時需要取消正在運行的線程,為此,在線程的執行路徑上引入取消點,并設置響應的處理函數,當需要取消線程運行時,可線程發送取消請求,當線運行至取消點時,將檢查是否由取消請求到達,當有取消請求到達時,執行響應的處理函數并退出運行。測試取消請求頭文件

#include<pthread.h>函數原型

voidpthread_testcancel(void);功能 測試線程的取消請求是否到達。參數 無參數。返回值 若取消請求已到達,結束線程,否則,立即返回。線程的取消狀態和類型

線程的取消有啟用和禁用兩種狀態,在禁用狀態下,線程收到的取消請求將被阻塞直至狀態被啟用;在啟用狀態下,線程會對收到的取消請求進行處理,具體方式取決于線程取消的類型設置線程的取消狀態頭文件

#include<pthread.h>函數原型

int

pthread_setcancelstate(intstate,int*oldstate);功能 設置線程的取消狀態。參數

state:取消狀態。

oldstate:原有狀態地址。返回值 成功返回0,失敗返回錯誤代碼。設置線程取消的處理類型頭文件

#include<pthread.h>函數原型

int

pthread_setcanceltype(inttype,int*oldtype);功能 設置線程取消的處理類型參數

type:處理類型。

oldtype:原處理類型地址。返回值 成功,返回0,失敗,返回錯誤代碼。線程清理函數

清理函數是線程取消時執行的函數,執行線程結束前的清理工作,以便線程安全退出。例如,釋放互斥鎖,以免死鎖的發生。

清理函數以棧的形式存放,通常,收到取消請求的線程在到達下一個取消點時,清理函數以后進先出的方式執行。設置清理函數pthread_cleanup_push/pthread_cleanup_pop函數頭文件

#include<pthread.h>函數原型

voidpthread_cleanup_push(void(*routine)(void*),void*arg); voidpthread_cleanup_pop(intexecute);功能 注冊/注銷線程清理函數。參數

routine:線程清理函數地址。

arg:傳遞的參數。

execute:執行標志。返回值 無返回值。發送取消請求pthread_cancel函數頭文件

#include<pthread.h>函數原型

int

pthread_cancel(pthread_tthread);功能 向線程發送取消請求。參數

thread:線程ID。返回值 成功返回0,失敗返回錯誤代碼。11.5線程同步互斥鎖

互斥鎖是一種管理臨界區訪問的同步控制機制,確保同一時間段僅有一個線程訪問臨界區、線程訪問臨界區前,需申請互斥鎖,只有獲得互斥鎖的線程允許進入臨界區,未獲得互斥鎖的線程進入等待狀態,直至獲得釋放的互斥鎖。互斥鎖的初始化頭文件

#include<pthread.h>函數原型

pthread_mutex_t

mutex=PTHREAD_MUTEX_INITIALIZER;

int

pthread_mutex_init(pthread_mutex_t*mp,pthread_mutexattr_t*mattr)

int

pthread_mutex_destroy(pthread_mutex_t*mp)功能 初始化/注銷互斥鎖。參數

mp:互斥鎖。

mattr:互斥鎖屬性。返回值 成功,返回0,失敗,返回錯誤代碼。申請/釋放互斥鎖pthread_mutex_lock/pthread_mutex_unlock函數頭文件

#include<pthread.h>函數原型

int

pthread_mutex_lock(pthread_mutex_t*mp)

int

pthread_mutex_unlock(pthread_mutex_t*mp)功能 申請/釋放互斥鎖。參數

mp:互斥鎖。返回值 成功返回0,失敗返回錯誤代碼。條件變量

條件變量是一種線程間基于條件的協調機制。,以條件變量的形式表示某種條件。當線程訪問的條件不成立,線程將在條件變量上等待,直至條件得到滿足。條件變量的相關函數屬于非信號安全函數。初始化條件變量(1)pthread_cond_t

cond=PTHREAD_COND_INITIALIZER;//靜態條件變量初始化(2)pthread_cond_init/pthread_cond_destroy函數頭文件

#include<pthread.h>函數原型

int

pthread_cond_init(pthread_cond_t*cv,pthread_condattr_t*cattr)

int

pthread_cond_destroy(pthread_cond_t*cv)功能 初始化/注銷條件變量。參數

cv:條件變量。

cattr:條件變量屬性。返回值 成功返回0,失敗返回錯誤代碼。等待/釋放條件變量thread_cond_wait/pthread_cond_signal函數頭文件

#include<pthread.h>函數原型

int

pthread_cond_wait(pthread_cond_t*cv,pthread_mutex_t*mutex)

int

pthread_cond_signal(pthread_cond_t*cv)

int

pthread_cond_broadcast(pthread_cond_t*cv)功能 等待/釋放條件變量參數

cv:條件變量。

mutex:互斥鎖。返回值 成功返回0,失敗返回錯誤代碼。11.6多線程環境下的信號處理內容提要多線程環境下的信號線程的信號掩碼多線程環境下的信號處理多線程環境下的信號

線程共享所屬進程的信號處理方式,信號可發送至進程或進程中的某個線程。對于面向進程的信號,信號被進程中所有線程共享,進程中任意線程可對信號進行處理,具體的執行線程取決于調度時機;對于面向線程的信號,僅由目標線程處理。線程的信號掩碼

線程有獨立的信號掩碼,線程的信號掩碼繼承自創建者進程。信號掩碼為若干信號構成的集合,用于定義阻塞的信號。設置線程的信號掩碼1.pthread_sigmask函數頭文件

#include<signal.h>函數原型

int

pthread_sigmask(inthow,constsigset_t*set,sigset_t*oldset);功能 設置線程的信號掩碼參數

how:操作方式。

set:新信號掩碼地址。

oldset:原信號掩碼地址。向線程發送信號pthread_kill/pthread_sigqueue函數頭文件

#include<signal.h>函數原型

int

pthread_kill(pthread_t

tid,int

sig);

int

pthread_sigqueue(pthread_t

tid,int

sig,constunionsigvalvalue);功能 向線程發送信號。參數

tid:線程ID。

Sig:信號編號。

Value:傳遞的數據。返回值 成功返回0,失敗返回錯誤代碼。多線程環境下的信號處理

由于線程與信號的異步特性,為簡化多線程環境下的信號處理,僅指定一個線程以同步方式處理到達的信號。將其他信號設置為阻塞狀態。該處理方式可避免線程與信號處理程序間的資源競爭,從而降低程序設計的復雜性,提高程序的可讀性和可靠性。11.7非線程安全函數的改造內容提要線程安全函數非線程安全函數非線程安全函數的改造線程的設計原則線程安全函數

當函數被多個線程同時調用時,若總能保證程序運行的正確性,則函數稱為線程安全函數。若函數及其引用的子函數未使用全局變量或靜態變量,則函數稱為可重入函數。可重入函數一定是信號安全函數,反之,未必成立。對于函數中引用的全局變量或靜態變量,若使用互斥鎖進行了控制,則也可使函數稱為信號安全的,非線程安全函數

當函數被多個線程同時調用時,若不能始終保持其正確性,則函數稱為非信號安全函數。

glibc中的某些函數由于編寫時間較早,誕生于線程出現之前,并未考慮多線程環境,有些函數的參數或返回值使用了全局變量或靜態變量,因此,它們為非線程安全函數。例如,ctime和readdir函數等。非線程安全函數strerror非線程安全函數的改造

非線程安全函數的安全化改造就是指在功能和接口不變的前提下,將其轉變為線程安全的函數,具體做法是將函數中的全局變量替換為線程持有變量,使每個線程擁有一份拷貝,以防止競爭現象的發生。根據轉換方法的不同,可進一步劃分為:1.線程持有數據2.線程局部存儲

線程持有數據

對于非線程安全函數中的全局/靜態變量,為每個線程創建一份稱為線程持有數據的拷貝,以避免資源競爭的發生。

POSIX提供了一系列接口函數,為每個全局/靜態變量創建一個以鍵值關聯的數組,數組以線程ID為索引存放線程持有的數據。初始化實例(1)pthread_once函數頭文件

#include<pthread.h>函數原型

int

pthread_once(pthread_once_t*once_control,void(*init_routine)(void));功能 僅初始化一次。參數

once_control:一次性控制變量。

init_routine:初始化函數地址。返回值 返回0。創建/刪除線程持有數據關聯的鍵值(2)pthread_key_create/pthread_key_delete函數頭文件

#include<pthread.h>函數原型

int

pthread_key_create(pthread_key_t*key,void(*destr_function)(void*));

int

pthread_key_delete(pthread_key_tkey);功能 創建/刪除鍵值。參數

Key:鍵值。

destr_function:析構函數。返回值 成功,返回0,失敗,返回非0。獲取/設置鍵值關聯的線程持有數據(3)pthread_getspecific/pthread_setspecific函數頭文件

#include<pthread.h>函數原型

void*pthread_getspecific(pthread_key_tkey);

int

pthread_setspecific(pthread_key_tkey,constvoid*pointer);功能 獲取/設置鍵值關聯的線程持有數據。參數

Key:鍵值。

pointer:線程持有數據地址。返回值

pthread_setspecific成功返回0,失敗返回非0。基于線程持有數據的安全化改造staticpthread_once_tonce=PTHREAD_ONCE_INIT;staticpthread_key_t

strerrorKey;voidbuffer_destroy(void*buf){

free(buf);}voidbuffer_key_alloc(void){

ints; s=pthread_key_create(&strerrorKey,buffer_destroy); if(s!=0) err(1,"pthread_key_createfailed\n");}char*strerror(int

nerr){

ints; char*buf; s=pthread_once(&once,buffer_key_alloc); if(s!=0) err(1,"pthread_oncefailed\

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論