多執行緒程式設計2 執行緒同步

2021-08-07 16:22:35 字數 2437 閱讀 7059

訊號量

訊號量通常有兩種:二進位制訊號量和計數訊號量。二進位制訊號量只有0和1兩種取值,計數訊號量有更大的取值範圍。

訊號量一般用來保護一段**,使其每次只能被乙個執行執行緒執行,要完成這個工作,可以使用二進位制訊號量。

有時,希望可以允許有限數目的執行緒執行一段指定的**,這時可以使用計數訊號量。

建立

#include 

int sem_init(sem_t *sem, int pshared, unsigned

int value);

// 功能:初始化乙個未命名的訊號量(unnamed semaphore)。

訊號量控制

#include 

int sem_post(sem_t *sem); // v

int sem_wait(sem_t *sem); // p

sem_post的作用是以原子操作的方式給訊號量的值加1

sem_wait函式以原子操作的方式將訊號量的值減1,但它會等待直到訊號量有個非零值才會開始減法操作。例如,對值為2的訊號量呼叫sem_wait,執行緒將繼續執行,但訊號量的值會減到1。如果對值為0的訊號量呼叫sem_wait,這個函式就會等待,直到有其它執行緒增加了該訊號量的值使其不再為0為止。

如果兩個執行緒同時在sem_wait函式上等待同乙個訊號量變為非零值,那麼當該訊號量被第三個執行緒增加1時,只有其中乙個等待執行緒將開始對訊號量減1,然後繼續執行,另外乙個執行緒還將繼續等待。

訊號量銷毀

#include 

int sem_destroy(sem_t *sem);

//這個函式的作用是,用完訊號量後對它進行清理,清理該訊號量所擁有的資源。如果你試圖清理的訊號量正被一些執行緒等待,就會收到乙個錯誤。

多執行緒併發應用程式有乙個經典的模型,即生產者/消費者模型。系統中,產生訊息的是生產者,處理訊息的是消費者,消費者和生產者通過乙個緩衝區進行訊息傳遞。生產者產生訊息後提交到緩衝區,然後通知消費者可以從中取出訊息進行處理。消費者處理完資訊後,通知生產者可以繼續提供訊息。

要實現這個模型,關鍵在於消費者和生產者這兩個執行緒進行同步。也就是說:只有緩衝區中有訊息時,消費者才能夠提取訊息;只有訊息已被處理,生產者才能產生訊息提交到緩衝區。

互斥量

互斥量(mutex)從概念上來說類似於乙個二進位制訊號量,即初始值為1的訊號量。互斥量被獲取之後就不能再被獲取,因此對互斥體的獲取和釋放操作常常稱為加鎖和解鎖操作。

互斥量只能由獲取它的執行緒進行釋放,如果違反這一原則,則結果是未定義的。

互斥量從本質上說是一把鎖,在訪問共享資源前對互斥量進行加鎖,在訪問完成後釋放互斥量上的鎖。對互斥量進行加鎖以後,任何其他試圖再次對互斥量加鎖的執行緒將會被阻塞直到當前執行緒釋放該互斥量。

初始化

互斥量用乙個pthread_mutex_t型的變數表示。使用互斥量之前需要對它進行初始化,其介面函式原型如下:

int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);

mutex引數指向要初始化的互斥量。attr引數指向乙個描述互斥量屬性的結構體。attr引數可以為null,表示使用預設屬性。

操作函式

互斥量的主要操作函式如下:

int pthread_mutex_lock(pthread_mutex_t *mutex);

int pthread_mutex_trylock(pthread_mutex_t *mutex);

int pthread_mutex_unlock(pthread_mutex_t *mutex);

pthread_mutex_lock()用於對mutex引數指向的互斥量進行加鎖。如果這時互斥量已經被鎖,則呼叫這個函式的執行緒將被阻塞,直到互斥量成為未鎖狀態。函式返回時,表示這個互斥量已經變為已鎖狀態,同時,函式的呼叫者成為這個互斥量的擁有者。

pthread_mutex_trylock()也用於對mutex引數指向的互斥量進行加鎖。如果這時互斥量已經被鎖,則函式以錯誤狀態返回。

pthread_mutex_unlock()用於對mutex引數指向的互斥量進行解鎖。如果這時互斥量是未鎖狀態或不是當前執行緒所擁有的,則結果未定義。 因此,互斥量必須在同一執行緒上成對出現。

銷毀 互斥量不用以後,應該使用下面的函式進行銷毀:

int pthread_mutex_destroy(pthread_mutex_t *mutex);

條件變數

假設有這樣一種情況:執行緒正在等待共享資料內某個條件出現,這時必須先解鎖,否則其他執行緒不可能更改共享資料。一種實現方式是,可以迴圈檢測共享資料,但是在檢測前要加鎖,檢測後又要解鎖,這樣效率會很低。

因此,在這種情況下,需要一種方法,使得當執行緒在等待某些條件的滿足時進入睡眠狀態,一旦條件滿足,執行緒就應該被喚醒繼續執行。這個方法就是使用posix條件變數。

多執行緒程式設計 2 執行緒的同步

在 多執行緒程式設計 系列第一篇講述了如何啟動執行緒,這篇講述執行緒之間存在競爭時如何確保同步並且不發生死鎖。執行緒不同步引出的問題 下面做乙個假設,假設有100張票,由兩個執行緒來實現乙個售票程式,每次執行緒執行時首先檢查是否還有票未售出,如果有就按照票號從小到大的順序售出票號最小的票,程式的 如...

多執行緒程式設計 2 執行緒的同步

多執行緒程式設計 2 執行緒的同步 分類 c 基礎 2010 01 10 20 18 5463人閱讀 34 收藏舉報 在 多執行緒程式設計 系列第一篇講述了如何啟動執行緒,這篇講述執行緒之間存在競爭時如何確保同步並且不發生死鎖。執行緒不同步引出的問題 下面做乙個假設,假設有100張票,由兩個執行緒來...

Linux多執行緒程式設計(2)執行緒同步

執行緒同步 a.mutex 互斥量 多個執行緒同時訪問共享資料時可能會衝突,這跟前面講訊號時所說的可重要性是同樣的問 題。假如 兩個執行緒都要把某個全域性變數增加1,這個操作在某平台需要三條指令完成 1.從記憶體讀變數值到暫存器 2.暫存器的值加1 3.將暫存器的值寫回記憶體 我們通過乙個簡單的程式...