Linux之線程同步——nptl線程庫(二)(施工中)

Linux之線程同步——nptl線程庫(二)(基礎代碼)

https://mp.csdn.net/postedit/90573953

 

提問:

  1. 線程同步是什麼意思?爲什麼需要線程同步?不同步會導致什麼後果?
  2. 線程同步有什麼方法,接口?如何使用?
  3. 如何使用線程條件變量?

基本常識:

  • 臨界區(critical section)是指訪問某一共享資源代碼片段。
  • 原子操作(atomic operation)是指訪問同一共享資源其他線程不應中斷該片段執行。
  • 儘管C語言的運算符看似簡單,其操作未必屬於原子操作
  • 自動變量(Automatic Variable)指的是局部作用域變量
  • 死鎖是指兩個或兩個以上的進程在執行過程中,由於競爭資源或者由於彼此通信而造成的一種阻塞的現象,若無外力作用,它們都將無法推進下去。此時稱系統處於死鎖狀態或系統產生了死鎖,這些永遠在互相等待的進程稱爲死鎖進程。

 

英文縮寫與全稱:

  • futex 全稱爲fast user space mutex 即快速用戶空間互斥量。
  • mutual exclusion 即互斥。
  • condition variable 即條件變量

1.線程同步是什麼意思?爲什麼需要線程同步?不同步會導致什麼後果?

  • 同步就是協同步調,按預定的先後次序進行運行。如進程、線程同步,可理解爲進程或線程A和B一塊配合,A執行到一定程度時要依靠B的某個結果,於是停下來,示意B運行;B依言執行,再將結果給A;A再繼續操作。(摘自百度百科)
  • 對於爲什麼需要線程同步?和不同步導致的後果?可以參考基本代碼中的第一個例子(鏈接在文章頂部)。

2.線程同步有什麼方法,接口?如何使用?

  • 線程同步的兩個工具:互斥量(mutex)和條件變量(condition variable)。互斥量可以幫助線程同步對共享資源的使用,條件變量則是在此之外的拾遺補缺,允許線程相互通知共享變量的狀態發生了變化。

一、互斥量

互斥量使用和接口

#include<pthread.h>

pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;

靜態分配互斥量。

int pthread_mutex_lock(pthread_mutex_t *mutex);

鎖定某一互斥量。
成功返回0,失敗返回錯誤號(正數)。
參數mutex表示互斥量。

int pthread_mutex_unlock(pthread_mutex_t *mutex);

將某一互斥量解鎖。
成功返回0,失敗返回錯誤號(正數)。
參數mutex表示互斥量。
  • 對於mutex互斥量,可以理解爲0鎖定狀態,1未鎖定狀態。線程1訪問時,如果mutex爲1,則線程讓mutex減一,然後進入裏面。這時候其他線程想要訪問,但由於mutex爲0,所以其他線程等待。直到線程1訪問結束,調用pthread_mutex_unlock()讓mutex加一,表示自身使用完畢。其他線程才能開始訪問臨界區,當然多個線程誰先訪問,這是不確定的。
  • 使用案例在代碼段(頂)。
  • Pthreads API 提供了 pthread_mutex_trylock()和pthread_mutex_timedlock()。這兩個函數與pthread_mutex_lock()有一些區別,可以參考手冊頁(manual page)來使用。

動態化初始互斥量及其銷燬

  • 靜態初始值PTHREAD_MUTEX_INITIALIZER,只能用於如下互斥量進行初始化:經由靜態分配且攜帶默認屬性。其他情況下,必須調用pthread_mutex_init()對互斥量進行動態初始化。
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t* attr);

動態初始化互斥量。
成功返回0,失敗返回對應錯誤號。
參數mutex爲互斥量
參數attr是指向pthread_mutexattr_t類型對象的指針,該對象在函數調用前已經經過了初始化處理,用於定義互斥量的屬性。
若將attr參數置爲NULL,則互斥量的各種屬性會取默認值。
  • SUSv3規定,初始化一個已初始化的互斥量將導致未定義的行爲,應當避免這一行爲。
  • 如下情況必須使用動態初始化:
  • 動態分配於堆中的互斥量。
  • 互斥量是在棧中分配的自動變量。
  • 初始化經由靜態分配,且不使用默認屬性的互斥量。
int pthread_mutex_destroy(pthread_mutex_t *mutex);

銷燬動態分配的互斥量。
成功返回0,失敗返回對應錯誤號。
  • 當不再需要經由自動或動態分配的互斥量時,應使用pthread_mutex_destroy()將其銷燬。(靜態分配的不需要)
  • 只有當互斥量處於未鎖定狀態,且後續也無任何線程企圖鎖定它時,將其銷燬纔是安全的。若互斥量駐留於動態分配的一片內存區域中,應在釋放(free)此內存區域前纔將其銷燬。對於自動分配的互斥量,也應在宿主函數返回前將其銷燬。
  • 經由pthread_mutex_destroy()銷燬的互斥量,可調用pthread_mutex_init()對其重新初始化。

互斥量的屬性

  • 由於很懶加上時間不夠,而且自身也不太懂,這一段跳過(有空再來補),有興趣可以看書或網上查。(萬分抱歉)
  • 放了一個書上的例子在代碼區(頂)3。

 

二、通知狀態的改變:條件變量(condition variable)

  • 互斥量防止多個線程同時訪問同一共享變量。條件變量允許一個線程就某個共享變量(或其他共享資源)的狀態變化通知其他線程,並讓其他線程等待(堵塞於)這一通知。
  • 代碼區(頂)4 提供了一個例子。表明了主線程不停地循環檢查變量avail的狀態,故而造成了CPU資源的浪費。採用條件變量這一問題就解決了。允許一個線程休眠直至獲得另一個線程的通知(收到信號)去執行某些操作。
  • 條件變量負責就共享變量的狀態改變發出通知,而互斥量提供對該共享變量訪問的互斥。

通知和等待條件變量

int pthread_cond_singal(pthread_cond_t *cond);

發出信號cond,使其他處於等待狀態的線程喚醒。只保證喚醒至少一條遭到阻塞的線程。
注意:如果先發信號,而其他線程還未進入等待,是沒有用的。
成功返回0,失敗返回錯誤號。


int pthread_cond_broadcase(pthread_cond_t *cond);

發出信號cond,喚醒所有遭阻塞的線程。
成功返回0,失敗返回錯誤號。

int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);

阻塞線程,等待信號。
成功返回0,失敗返回錯誤號。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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