POSIX執行緒程式設計起步(2)-執行緒同步 (轉)
2.執行緒同步
POSIX提供了兩種用於執行緒同步的原語,這兩種操作分別是互斥以及條件變數。互斥是一種簡單的進行鎖定的原語,其主要作用是控制對共享資源的訪問,防止衝突。關於多執行緒,有一點值得大家注意,那就是整個的地址空間有所有的執行緒共享。其結果是幾乎所有的資源都可以被共享——比如全域性變數、描述符等。另一方面,在每個執行緒的入口(由pthread_create)內,以及由該函式呼叫的其他函式內,我們都會定義一些私有的區域性變數。在多執行緒程式中,全域性變數與區域性變數總是被混合使用,要想使多執行緒程式順利的執行,各執行緒對共享資源的訪問必須得到控制。
以下是一個生產者/消費者程式。生產者與消費者對共享緩衝區的訪問由互斥進行控制。
void * reader_function(void *);
void * writer_function(void *);
char buffer;
int buffer_has_item = 0;
pthread_mutex_t mutex;
struct timespec delay;
main()
{
pthread_t reader;
delay.tv_sec = 2;
delay.tv_nsec = 0;
pthread_mutex_init(&mutex, pthread_mutexattr_default);
pthread_create( &reader, pthread_attr_default, reader_function,
NULL);
writer_function();
}
void * writer_function(void *)
{
while(1)
{
pthread_mutex_lock( &mutex );
if ( buffer_has_item == 0 )
{
buffer = make_new_item();
buffer_has_item = 1;
}
pthread_mutex_unlock( &mutex );
pthread_delay_np( &delay );
}
}
void * reader_function(void *)
{
while(1)
{
pthread_mutex_lock( &mutex );
if ( buffer_has_item == 1)
{
consume_item( buffer );
buffer_has_item = 0;
}
pthread_mutex_unlock( &mutex );
pthread_delay_np( &delay );
}
}
上邊這個簡單的例子程式中,共享緩衝區只能儲存一個共享資料項。因此該緩衝區只有兩個狀態:“有”/“無”。生產者在向緩衝區寫入資料前,首先會將互斥上鎖,如果該互斥已被鎖定,則生產者將阻塞直到互斥被解鎖。生產者鎖定了互斥以後,將會檢查緩衝區是否為空(透過標誌變數buffer_has_item)。如果緩衝區沒有資料,生產者就會產生新資料項放入緩衝區,並設定標誌變數以使得消費者可以知道是否能進行消費。接下來生產者解除對互斥的鎖定並等待,這樣消費者應該有充足的時間來訪問緩衝區。
消費者採取了相似的過程來訪問緩衝區。它首先鎖定互斥,檢查標誌變數,如果可能則消費掉僅有的資料項。接著消費者解鎖互斥並等待一小會兒好讓生產者有時間寫入新的資料項。
上例中,生產者和消費者將會持續不斷的執行,不斷的生產、消費。事實上,在通常的程式中,如果確定不再使用某個互斥,則應該用pthread_mutex_destroy(&mutex)將其摧毀。順便提一句,在使用某個互斥之前,應該使用pthread_mutex_init()將其初始化。在我們的例子中,初始化時使用了兩個引數,第一個用來指定被初始化的互斥,第二個則是該互斥的屬性。(在DEC O/1上,互斥的屬性沒有實際意義,通常使用PTHREAD_MUTEXATTR_DEFAULT)
對互斥的正確使用可以有效地減少競爭條件。其實互斥本身是非常簡單的,只有兩個狀態:鎖定、未鎖定。它能實現的功能也是有限的。POSIX還提供了條件變數這一有力工具來補充互斥的不足。使用條件變數,一個執行緒可以在已經鎖定互斥的情況下被阻塞並等待喚醒訊號,而其他執行緒仍能訪問被鎖定的共享資源。當另外的某一個執行緒發出訊號後,被阻塞的執行緒將被喚醒並依然可以訪問阻塞前自己鎖定的共享資源。由此,互斥和條件變數的聯合使用可以幫助我們避免迴圈死鎖的情況出現。我們利用互斥和條件變數設計了一個僅有單一整數訊號燈的庫。庫的可以在附錄A中找到,關於條件變數的說明可以在手冊頁(man pages)裡找到
本節涉及的函式:
pthread_mutex_init(), pthread_mutex_lock(),
pthread_mutex_unlock(), and pthread_mutex_destroy().
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10748419/viewspace-960949/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- C#多執行緒程式設計-基元執行緒同步構造C#執行緒程式設計
- 多執行緒(2)-執行緒同步互斥鎖Mutex執行緒Mutex
- [短文速讀 -5] 多執行緒程式設計引子:程式、執行緒、執行緒安全執行緒程式設計
- 【轉】1.1非同步程式設計:執行緒概述及使用非同步程式設計執行緒
- java併發程式設計——執行緒同步Java程式設計執行緒
- 多執行緒(2)-執行緒同步條件變數執行緒變數
- 併發程式設計之多執行緒執行緒安全程式設計執行緒
- 多執行緒和多執行緒同步執行緒
- 【多執行緒總結(二)-執行緒安全與執行緒同步】執行緒
- 多執行緒------執行緒與程式/執行緒排程/建立執行緒執行緒
- JavaScript 單執行緒之非同步程式設計JavaScript執行緒非同步程式設計
- Java多執行緒程式設計筆記2:synchronized同步方法Java執行緒程式設計筆記synchronized
- 多執行緒程式設計基礎(一)-- 執行緒的使用執行緒程式設計
- 最全java多執行緒總結2--如何進行執行緒同步Java執行緒
- Java多執行緒學習(3)執行緒同步與執行緒通訊Java執行緒
- Java多執行緒(2)執行緒鎖Java執行緒
- Java併發程式設計之執行緒安全、執行緒通訊Java程式設計執行緒
- C#多執行緒程式設計實戰1.1建立執行緒C#執行緒程式設計
- 多執行緒程式設計基礎(二)-- 執行緒池的使用執行緒程式設計
- 執行緒的同步執行緒
- 執行緒同步方法執行緒
- 理解執行緒同步執行緒
- 深入執行緒同步執行緒
- python 多執行緒程式設計Python執行緒程式設計
- JavaScript多執行緒程式設計JavaScript執行緒程式設計
- Python多執行緒程式設計Python執行緒程式設計
- 程式執行緒篇——程式執行緒基礎執行緒
- 執行緒(2)執行緒
- Java多執行緒之執行緒同步【synchronized、Lock、volatitle】Java執行緒synchronized
- C#多執行緒開發-執行緒同步 02C#執行緒
- 多執行緒Demo學習(執行緒的同步,簡單的執行緒通訊)執行緒
- 什麼是程式(執行緒)同步執行緒
- 執行緒(一)——執行緒,執行緒池,Task概念+程式碼實踐執行緒
- 玩轉java多執行緒 之多執行緒基礎 執行緒狀態 及執行緒停止實戰Java執行緒
- 非同步/同步,阻塞/非阻塞,單執行緒/多執行緒概念梳理非同步執行緒
- 執行緒與同步非同步執行緒非同步
- Android程式框架:執行緒與執行緒池Android框架執行緒
- 程式執行緒篇——執行緒切換(上)執行緒
- 程式執行緒篇——執行緒切換(下)執行緒