pthread.h 相關(guān)函數(shù)使用方法集錦之線程同步變量

前言

pthread(POSIX thread)骗奖,簡稱為pthread嫩舟,是線程的POSIX標(biāo)準(zhǔn),在類Unix操作系統(tǒng)中(Unix叛复、Linux仔引、Mac OS X等)扔仓,都是用pthread作為操作系統(tǒng)的線程。<pthread.h>作為其編程標(biāo)準(zhǔn)的頭文件咖耘,本文探討里面的常用函數(shù)意義以及使用方法翘簇。

在多線程編程中,操作系統(tǒng)引入了鎖機(jī)制儿倒。通過鎖機(jī)制版保,能夠保證在多核多線程環(huán)境中,在某一個時間點(diǎn)上夫否,只能有一個線程進(jìn)入臨界區(qū)代碼彻犁,從而保證臨界區(qū)中操作數(shù)據(jù)的一致性。

在pthread里面實(shí)現(xiàn)了5中同步變量凰慈,分別是互斥鎖(mutex)汞幢、自旋鎖(spinlock)、條件變量(condition)溉瓶、讀寫鎖(rwlock)以及柵欄(barrier)急鳄。

線程同步變量

pthread互斥鎖(mutex)

互斥鎖是一個二元變量,其狀態(tài)為開鎖(允許0)和上鎖(禁止1)堰酿,將某個共享資源與某個特定互斥鎖在邏輯上綁定(要申請該資源必須先獲取鎖)。

訪問公共資源前张足,必須申請該互斥鎖触创,若處于開鎖狀態(tài),則申請到鎖對象为牍,并立即占有該鎖哼绑,以防止其他線程訪問該資源;如果該互斥鎖處于鎖定狀態(tài)碉咆,則阻塞當(dāng)前線程抖韩。

只有鎖定該互斥鎖的進(jìn)程才能釋放該互斥鎖,其他線程試圖釋放無效疫铜∶。互斥鎖使用的非常廣泛,在所有線程同步變量中壳咕,可以重點(diǎn)關(guān)注席揽。

pthread_mutex_t

鎖類型,定義互斥鎖谓厘。

pthread_mutex_init

初始化互斥鎖幌羞。

pthread_mutex_lock

申請互斥鎖并占有互斥鎖,其他線程無法訪問該資源竟稳。

pthread_mutex_trylock

pthread_mutex_unlock

釋放互斥鎖属桦,此時其他線程可以訪問該資源熊痴。

pthread_mutex_destroy

釋放鎖資源。

pthread條件變量(condition)

條件變量是利用線程間共享的全局變量進(jìn)行同步的一種機(jī)制聂宾,主要包括兩個動作:一個線程等待"條件變量的條件成立"而掛起愁拭;另一個線程使"條件成立"(給出條件成立信號)。為了防止競爭亏吝,條件變量的使用總是和一個互斥鎖結(jié)合在一起岭埠。

pthread_cond_t

pthread_cond_init

pthread_cond_signal

pthread_cond_wait

pthread_cond_broadcast

pthread_cond_wait的使用

pthread_cond_wait總是和一個互斥量同時使用的,我們看看APUE中關(guān)于pthread_cond_wait使用的原話:

傳遞給pthread_cond_wait的互斥量對條件(condition)進(jìn)行保護(hù)蔚鸥。調(diào)用者把鎖住的互斥量傳給函數(shù)惜论,函數(shù)然后自動把調(diào)用線程放在等待條件(condition)的線程列表上,對互斥量進(jìn)行解鎖止喷。這就關(guān)閉了條件檢查線程進(jìn)入休眠狀態(tài)等待條件改變這兩個操作之間的時間通道馆类,線程就不會錯過條件(condition)的任何變化。

這段話說明了為什么需要互斥量來保護(hù)條件變量弹谁,因?yàn)?strong>條件檢查和線程進(jìn)入休眠狀態(tài)等待條件改變這兩個操作都不是線程安全的乾巧,所以需要互斥量進(jìn)行保護(hù)。

pthread_mutex_lock(&mutex);
pthread_cond_wait(&condition, &mutex);
pthread_mutex_unlock(&mutex);

我們再來看看互斥量傳參進(jìn)入pthread_cond_wait時预愤,pthread_cond_wait對互斥量做了什么操作沟于。再來回味一下上面APUE的這段話:

調(diào)用者把鎖住的互斥量傳給函數(shù),函數(shù)然后自動把調(diào)用線程放在等待條件(condition)的線程列表上植康,對互斥量進(jìn)行解鎖旷太。

也就是pthread_cond_wait里面做了兩個操作,第一個操作是將調(diào)用線程放在等待條件的線程列表上销睁;第二個操作是將互斥量解鎖供璧。

注意,將互斥量解鎖以后pthread_cond_wait并沒有返回冻记,而是等待條件成立睡毒,等條件成立時,pthread_cond_wait會再次獲得互斥量冗栗。

所以pthread_cond_wait對互斥量的操作實(shí)際上是這樣子的演顾。

| -- pthread_mutex_lock lock 互斥量          (1)
|
| -- 進(jìn)入pthread_cond_wait函數(shù)邏輯
| -- unlock 互斥量                           (2)
|
| -- 等待條件成立
|
| -- lock 互斥量                             (3)
|
| -- 退出pthread_cond_wait函數(shù)邏輯
|
| -- pthread_mutex_unlock unlock 互斥量      (4)

在這個過程中,互斥量實(shí)際上是已經(jīng)被鎖住了兩次贞瞒。

我們編寫一個死鎖的例子舉證一下上面的過程偶房,在這個例子我們驗(yàn)證pthread_cond_wait是否會lock互斥量,進(jìn)入pthread_cond_wait時军浆,互斥量是沒有鎖住的棕洋,在pthread_cond_wait返回之后,別的線程嘗試獲取鎖乒融,如果卡死掰盘,那便說明pthread_cond_wait里面有l(wèi)ock互斥量的操作摄悯。

#include <iostream>
#include <unistd.h>
#include <pthread.h>

using namespace std;

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

void* test(void *p){
    pthread_mutex_lock(&mutex);  //  (1)
    pthread_mutex_unlock(&mutex); // (4)
    cout << "child thread wait condition. " << endl;
    pthread_cond_wait(&cond, &mutex); // (2) (3)
    cout << "child thread get condition. " << endl;
    cout << "child thread return." << endl;
    // pthread_mutex_unlock(&mutex);
}

int main()
{
    pthread_t tid;
    pthread_create(&tid, NULL, test, NULL);
    sleep(1); // 保證子線程先啟動
    cout << "main thread signal condition. " << endl;
    pthread_cond_signal(&cond);
    sleep(1); // 保證子線程能夠先得到收到條件并處理完
     cout << "main thread acquire lock. " << endl;
    pthread_mutex_lock(&mutex); // 嘗試獲取鎖
    cout << "main thread acquire lock success. " << endl;
}

/* =========================================================================
 * 輸出
 *
 * child thread wait condition.
 * main thread signal condition.
 * child thread get condition.
 * child thread return.
 * main thread acquire lock.
 *
 * =========================================================================
 */

在子線程返回后,主線程會一直卡在acquire lock這里愧捕,不會success奢驯,說明在pthread_cond_wait里面確實(shí)有加鎖的操作,此時如沒有釋放鎖次绘,其他線程獲取鎖將會進(jìn)入死鎖狀態(tài)瘪阁,所以在pthread_cond_wait使用前后,一定要使用pthread_mutex_lock和pthread_mutex_unlock邮偎。

pthread自旋鎖(spinlock)

自旋鎖與互斥鎖比較類似管跺,它們都是為了解決對某項(xiàng)資源的互斥使用。無論是互斥鎖禾进,還是自旋鎖豁跑,在任何時刻罗岖,最多只能有一個保持者单料,也就說,在任何時刻最多只能有一個執(zhí)行單元獲得鎖骏掀。但是兩者在調(diào)度機(jī)制上略有不同宠纯。對于互斥鎖卸夕,如果資源已經(jīng)被占用,資源申請者只能進(jìn)入睡眠狀態(tài)征椒。但是自旋鎖不會引起調(diào)用者睡眠娇哆,如果自旋鎖已經(jīng)被別的執(zhí)行單元保持,調(diào)用者就一直循環(huán)在那里看是否該自旋鎖的保持者已經(jīng)釋放了鎖勃救,"自旋"一詞就是因此而得名。

pthread_spinlock_t

pthread_spin_init

pthread_spin_destroy

pthread_spin_lock

pthread_spin_trylock

pthread_spin_unlock

pthread讀寫鎖(rwlock)

讀寫鎖實(shí)際是一種特殊的自旋鎖治力,它把對共享資源的訪問者劃分成讀者和寫者蒙秒,讀者只對共享資源進(jìn)行讀訪問,寫者則需要對共享資源進(jìn)行寫操作宵统。這種鎖相對于自旋鎖而言晕讲,能提高并發(fā)性,因?yàn)樵诙嗵幚砥飨到y(tǒng)中马澈,它允許同時有多個讀者來訪問共享資源瓢省,最大可能的讀者數(shù)為實(shí)際的邏輯CPU數(shù)。寫者是排他性的痊班,一個讀寫鎖同時只能有一個寫者或多個讀者(與CPU數(shù)相關(guān))勤婚,但不能同時既有讀者又有寫者

pthread_rwlock_t

pthread_rwlock_init

pthread_rwlock_wrlock

pthread_rwlock_rdlock

pthread_rwlock_unlock

pthread_rwlock_tryrdlock

pthread_rwlock_trywdlock

pthread_rwlock_destroy

pthread柵欄(barrier)

柵欄(Barrier)是并行計算中的一種同步方法涤伐。對于一群進(jìn)程或線程馒胆,程序中的一個同步屏障意味著任何線程/進(jìn)程執(zhí)行到此后必須等待缨称,直到所有線程/進(jìn)程都到達(dá)此點(diǎn)才可繼續(xù)執(zhí)行下文。

pthread_barrier_t

pthread_barrier_init

pthread_barrier_wait

pthread_barrier_destroy

原文鏈接

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末祝迂,一起剝皮案震驚了整個濱河市睦尽,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌型雳,老刑警劉巖当凡,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異纠俭,居然都是意外死亡沿量,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進(jìn)店門柑晒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來欧瘪,“玉大人,你說我怎么就攤上這事匙赞》鹨矗” “怎么了?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵涌庭,是天一觀的道長芥被。 經(jīng)常有香客問我,道長坐榆,這世上最難降的妖魔是什么拴魄? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮席镀,結(jié)果婚禮上匹中,老公的妹妹穿的比我還像新娘。我一直安慰自己豪诲,他們只是感情好顶捷,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著屎篱,像睡著了一般服赎。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上交播,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天重虑,我揣著相機(jī)與錄音,去河邊找鬼秦士。 笑死缺厉,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播芽死,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼乏梁,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了关贵?” 一聲冷哼從身側(cè)響起遇骑,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎揖曾,沒想到半個月后落萎,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡炭剪,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年练链,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片奴拦。...
    茶點(diǎn)故事閱讀 38,163評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡媒鼓,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出错妖,到底是詐尸還是另有隱情绿鸣,我是刑警寧澤,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布暂氯,位于F島的核電站潮模,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏痴施。R本人自食惡果不足惜擎厢,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望辣吃。 院中可真熱鬧动遭,春花似錦、人聲如沸神得。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽循头。三九已至,卻和暖如春炎疆,著一層夾襖步出監(jiān)牢的瞬間卡骂,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工形入, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留全跨,地道東北人。 一個月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓亿遂,卻偏偏與公主長得像浓若,于是被迫代替她去往敵國和親渺杉。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評論 2 344

推薦閱讀更多精彩內(nèi)容

  • linux編程-線程 MUTEX 一.概述 互斥量是線程同步的一...
    Aska偶陣雨閱讀 477評論 0 0
  • Q:為什么出現(xiàn)多線程挪钓? A:為了實(shí)現(xiàn)同時干多件事的需求(并發(fā))是越,同時進(jìn)行著下載和頁面UI刷新。對于處理器碌上,為每個線...
    幸福相依閱讀 1,570評論 0 2
  • 線程 在linux內(nèi)核那一部分我們知道倚评,線程其實(shí)就是一種特殊的進(jìn)程,只是他們共享進(jìn)程的文件和內(nèi)存等資源馏予,無論如何對...
    大雄good閱讀 662評論 0 2
  • 線程 線程的概念 典型的UNIX進(jìn)程可以看成只有一個控制線程:一個進(jìn)程在同一時刻只做一件事天梧。有了多個控制線程后,在...
    ColdWave閱讀 1,451評論 0 0
  • 1,2017年1月21日開始吃地瓜餐,約20日后開始膚色發(fā)黃蛹尝,當(dāng)時吃的黃的多后豫!65天停后,膚色漸漸變回來了箩言!中間黃...
    南得糊涂呀閱讀 935評論 0 1