天天看點

20191221第四章學習筆記

線程優點:

(1)線程建立和切換速度更快:程序的上下文複雜而龐大。其複雜性主要來自管理程序映像的需要。例如,在具有虛拟記憶體的系統中。程序映像可能由叫作頁面的許多記憶體單元組成。在執行過程中。有些頁面在記憶體中,有些則不在記憶體中。作業系統核心必須使用多個頁表和多個級别的硬體輔助來跟蹤每個程序的頁面,要想建立新的程序,作業系統必須為進 程配置設定記憶體并建構頁表。若要在某個程序中建立線程,作業系統不必為新的線程配置設定記憶體和建立頁表,因為線程與程序共用同一個位址空間。是以,建立線程比建立程序更快。另外,由于以下原因,線程切換比程序切換更快。程序切換涉及将一個程序的複雜分貞環境 替換為另一個程序的複雜分頁環境,需要大量的操作和時間。相比之下,同一個程序中的線程切換要簡單得多、也快得多,因為作業系統核心隻需要切換執行點,而不需要更改程序映像。

(2)線程的響應速度更快:一個程序隻有一個執行路徑。當某個程序被挂起時,整個程序都将停止執行。相反,當某個線程被挂起時,同程序中的其他線程可以繼續執行。這使得有多個線程的程式響應速度更快.例如,在一個多線程的程序中,當一個線程被阻塞以等待I/O時,其他線程仍可在背景進行計算。在有線程的伺服器中,伺服器可同時服務多個客戶機。

(3)線程更适合并行計算:并行計算的目标是使用多個執行路徑更快地解決問題。基于分治原則(如二叉樹查找和快速排序等)的算法經常表現出高度的并行性,可通過使用并行或并發執行來提高計算速度。這種算法通常要求執行實體共享公用資料。在程序模型中,各程序不能有效共享資料,因為它們的位址空間都不一樣。為了解決這個問題,程序必須使用程序間通信(IPC)來交換資料或使用其他方法将公用資料區包含到其位址空間中。相反,同一程序中的所有線程共享同一位址空間中的所有(全局)資料。是以,使用線程編寫并行執行的程式比使用程序編寫更簡單、更自然。

線程缺點:(1)由于位址空間共享,線程需要來自使用者的明确同步。

(2)許多庫函數可能對線程不安全,例如傳統strtok()函數将一個字元串分成一連串令 牌。通常,任何使用全局變量或依賴于靜态記憶體内容的函數.線程都不安全。為了使庫函數 适應線程環境,還需要做大量的工作。

(3)在單CPU系統上,使用線程解決問題實際上要比使用順序程式慢,這是由在運作 時建立線程和切換上下文的系統開銷造成的。

線程建立:

使用pthread_create()函數建立線程。

int prhread_create (pthread_t *pthread_id,pthread_attr_t *attr,

Void (func)(void *), void *arg);

如果成功則傳回0,如果失敗則傳回錯誤代碼。其中,attr參數最複雜。下面給出了attr參數的使用步驟。

定義一個pthread屬性變量 pthread_attr_t attr。

用pthread_attr_init(&attr)初始化屬性變量。

設定屬性變量并在 pthread_create()調用中使用。

必要時,通過 pthread_attr_destroy(&attr)釋放 attr資源。

線程ID:

線程ID是一種不透明的資料類型,取決于實作情況。是以,不應該直接比較線程ID。如果需要,可以使用pthread_equal()函數對線程ID進行比較。

int pthread_equal (pthread_t t1, pthread_t t2);

如果是不同的線程,則傳回0,否則傳回非0。

線程終止:

線程函數結束後,線程即終止。或者,線程可以調用函數

int pthread_exit (void *status);

進行顯示終止,其中狀态是線程的退出狀态。通常,0退出值表示正常終止,非0隻表示異常終止。

線程連接配接:

一個線程可以等待另一個線程的終止,通過:

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

終止線程退出狀态以status_ptr傳回。

線程同步

當多個線程試圖修改同一共享變量或資料結構時,如果修改結果取決于線程的執行順序,則稱之為競态條件

在并發程式中,絕不能有競态條件。否則,覺果可能不一緻。

并發執行的線程通常需要互相協作,防止出現競态條件,線程需要同步。

互斥量

在 Pthread中,鎖被稱為互斥量,意思是互相排斥。互斥變呈是用 ptbread_mutex_t 類型聲明的在使,用之前必須對它們進行初始化。有兩種方法可以初始化互斥址。

靜态方法:

pthreaa—mutex_t m = PTHREAD_MUTEX_INITIALIZER;

定義互斥量 m, 并使用預設屬性對其進行初始化。