国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

linux:線程同步

這篇具有很好參考價(jià)值的文章主要介紹了linux:線程同步。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

linux:線程同步,Linux,linux,運(yùn)維

個(gè)人主頁(yè) : 個(gè)人主頁(yè)
個(gè)人專欄 : 《數(shù)據(jù)結(jié)構(gòu)》 《C語(yǔ)言》《C++》《Linux》


前言

本文作為我對(duì)于線程同步知識(shí)總結(jié)


線程同步

  • 同步:在保證數(shù)據(jù)安全的前提下,讓線程能夠按照某種順序訪問(wèn)臨界資源,從而有效避免饑餓問(wèn)題,叫做同步
  • 競(jìng)態(tài)條件:是指多個(gè)線程同時(shí)訪問(wèn)系統(tǒng)共享資源時(shí),由于其執(zhí)行順序或時(shí)間上的不確定性,導(dǎo)致數(shù)據(jù)不一致或其它不可預(yù)料的結(jié)果(一般發(fā)生在對(duì)稱多處理環(huán)境,中斷和異常處理,內(nèi)核態(tài)搶占,并發(fā)執(zhí)行…)

看了上面兩個(gè)概念,你可能還是不太理解同步是什么,為什么要有同步。下面我們就舉一個(gè)例子。
我們假定有兩個(gè)人,一個(gè)人A將蘋果放在桌子上,另一個(gè)人B蒙著眼睛去桌子上拿蘋果,桌子每次只允許有一個(gè)人,因?yàn)锽不清楚桌子上的情況是什么(有一個(gè)蘋果,沒(méi)有蘋果,桌子上全是蘋果),那為了保險(xiǎn)起見(jiàn),B只能瘋狂的去桌子上拿蘋果,以保證B拿到所有的蘋果。那如果桌子上沒(méi)有蘋果,B仍然瘋狂去桌子上拿蘋果,此時(shí)A是不是就不能去桌子上放蘋果,那此時(shí)B是不是再做無(wú)用工,而且導(dǎo)致了A不能放蘋果,B拿蘋果的效率降低。如果我們將A,B換成線程,蘋果看出共享資源(某種任務(wù)),桌子看成臨界區(qū),那B是不是就是一直在做申請(qǐng)鎖,再釋放鎖的無(wú)效工作,并且導(dǎo)致了A的饑餓問(wèn)題。這時(shí)我們就需要保證A,B之間的順序問(wèn)題,如在B訪問(wèn)過(guò)桌子后,不能立即再次訪問(wèn)桌子,要等待A訪問(wèn)桌子后。這是不是就會(huì)使A,B拿蘋果的效率提升。而這就是為什么要有同步的理由

條件變量接口

初始化條件變量

  • 靜態(tài)初始化linux:線程同步,Linux,linux,運(yùn)維
    與互斥鎖類似,定義一個(gè)全局的條件變量,用PTHREAD_COND_INITIALIZER宏來(lái)初始化,系統(tǒng)自動(dòng)釋放該條件變量。該宏一般存放在 /usr/include/pthread.h 路徑下
    linux:線程同步,Linux,linux,運(yùn)維
  • 動(dòng)態(tài)初始化
    linux:線程同步,Linux,linux,運(yùn)維
    restrict是C語(yǔ)言的一個(gè)關(guān)鍵字,表示該指針是唯一的訪問(wèn)其指向?qū)ο蟮闹羔槨?br> cond將被初始化的條件變量,attr 為nullptr,使用默認(rèn)屬性初始化條件變量。
    如果函數(shù)成功執(zhí)行,返回0; 如果函數(shù)執(zhí)行失敗,則返回錯(cuò)誤碼,如EAGAIN(資源暫時(shí)不可用),ENOMEM(內(nèi)存不足)

銷毀條件變量
linux:線程同步,Linux,linux,運(yùn)維
cond 表示將被銷毀的條件變量,需要注意在調(diào)用pthread_cond_destroy后,該指針本身并未被銷毀,只是所指向的條件變量被銷毀,記得將指針置空
如果函數(shù)成功執(zhí)行,返回0; 如果函數(shù)失敗,返回錯(cuò)誤碼。如EBUSY,該條件變量正在被使用


等待條件變量
linux:線程同步,Linux,linux,運(yùn)維
cond 表示將要等待的條件變量,mutex 表示線程所持有的互斥鎖
如果函數(shù)成功執(zhí)行,返回0;如果函數(shù)執(zhí)行失敗,返回錯(cuò)誤碼,如EINVAL 無(wú)效的參數(shù)(條件變量 or 互斥鎖為初始化…)

關(guān)于該函數(shù)的參數(shù)為什么會(huì)有鎖,有什么注意事項(xiàng),在下面代碼示例,我們?cè)俳忉尅?/p>


喚醒等待

linux:線程同步,Linux,linux,運(yùn)維
cond要發(fā)生信號(hào)的條件變量指針。
如果函數(shù)執(zhí)行成功,返回0; 如果函數(shù)執(zhí)行失敗,返回錯(cuò)誤碼,如ENVAL(無(wú)效的參數(shù))
需要注意的是,pthread_cond_signal只用于喚醒在cond條件變量的阻塞隊(duì)列中等待的一個(gè)線程。

linux:線程同步,Linux,linux,運(yùn)維
該函數(shù)的參數(shù)與返回值與pthread_cond_signal相同,只不過(guò)該函數(shù)喚醒所有在cond條件變量的阻塞隊(duì)列中等待的所有線程,而那些線程先執(zhí)行,取決于操作系統(tǒng)的調(diào)度策略。


簡(jiǎn)單示例

我們先來(lái)看看下面代碼,3個(gè)線程爭(zhēng)奪ticket資源。當(dāng)三個(gè)線程檢測(cè)到ticket == 0時(shí),三個(gè)線程都將等待。我們主線程每過(guò)5秒,使ticket += 10。

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

using namespace std;

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int ticket = 100;

void* threadRoutine(void *args)
{
    const string threadname = static_cast<char*>(args);
    
    while(true)
    {   
        usleep(1000);
        pthread_mutex_lock(&mutex);
        if(ticket > 0)
        {
            ticket--;
            cout << threadname << ", get a ticket: " << ticket << endl;
        }
        else
        {
            cout << threadname << ", ticket == 0" << endl;
            pthread_cond_wait(&cond, &mutex);
        }
        pthread_mutex_unlock(&mutex);
    }

    return nullptr;
}

int main()
{
    pthread_t td1;
    pthread_create(&td1, nullptr, threadRoutine, (void*)"thread-1");

    pthread_t td2;
    pthread_create(&td2, nullptr, threadRoutine, (void*)"thread-2");

    pthread_t td3;
    pthread_create(&td3, nullptr, threadRoutine, (void*)"thread-3");
    
    while(true)
    {
        sleep(5);
        pthread_mutex_lock(&mutex);
        ticket += 10;
        pthread_mutex_unlock(&mutex);

        pthread_cond_signal(&cond);
    }

    pthread_join(td1, nullptr);
    pthread_join(td2, nullptr);
    pthread_join(td3, nullptr);
    return 0;
}

linux:線程同步,Linux,linux,運(yùn)維
當(dāng)線程2,線程3,線程1先后檢測(cè)到ticket == 0時(shí),在cond的等待隊(duì)列中,線程以2,3,1的順序排隊(duì)。那當(dāng)調(diào)用pthread_cond_signal函數(shù)時(shí),線程2會(huì)先執(zhí)行,執(zhí)行完再檢測(cè)到ticket==0,排到等待隊(duì)列尾部
linux:線程同步,Linux,linux,運(yùn)維
再調(diào)用pthread_cond_signal函數(shù)時(shí),線程3會(huì)執(zhí)行。
linux:線程同步,Linux,linux,運(yùn)維
再調(diào)用pthread_cond_signal函數(shù)時(shí),線程1會(huì)執(zhí)行。
linux:線程同步,Linux,linux,運(yùn)維
這樣,我們多線程就可以按某種特定順序來(lái)執(zhí)行。
那如果我們使用pthread_cond_broadcast函數(shù),會(huì)有什么情況?
linux:線程同步,Linux,linux,運(yùn)維
我們會(huì)發(fā)現(xiàn),三個(gè)線程都被喚醒,來(lái)爭(zhēng)搶ticket資源,其先后順序由操作系統(tǒng)決定(優(yōu)先級(jí),競(jìng)爭(zhēng)鎖的能力…)。


pthread_cond_wait為什么要有mutex

此時(shí)不知道你是否有一個(gè)疑問(wèn),我們假定線程-1先爭(zhēng)搶到ticket,檢測(cè)到ticket == 0時(shí),該線程-1要在cond的等待隊(duì)列中等待,然后其它兩個(gè)線程在進(jìn)入臨界區(qū),檢測(cè)到ticket==0,在等待隊(duì)列中排隊(duì)。但是線程-1是持有鎖進(jìn)入等待隊(duì)列的,那其它兩個(gè)線程是如何進(jìn)入臨界區(qū)的?答案很明顯,那就是線程-1在cond等待中,一定釋放了其持有的鎖,從而使其余兩個(gè)線程可以持有鎖進(jìn)入臨界區(qū)。這就是為什么pthread_cond_wait函數(shù)的參數(shù)要有互斥鎖的存在。
那我們?cè)谏钊胂胍幌?,調(diào)用pthread_cond_wait函數(shù)后,該線程是先釋放鎖,再進(jìn)入等待隊(duì)列中;還是先進(jìn)入等待隊(duì)列中,再釋放鎖?答案是都不是。釋放鎖和進(jìn)入等待隊(duì)列是同時(shí)進(jìn)行的!?。∵@也表示pthread_cond_wait函數(shù)是原子的,在調(diào)用pthread_cond_wait時(shí),涉及的互斥鎖釋放和進(jìn)入等待隊(duì)列的操作是作為一個(gè)不可分割的整體來(lái)執(zhí)行。確保了線程在調(diào)用該函數(shù)時(shí)不會(huì)遇到競(jìng)態(tài)條件,即線程在釋放鎖和進(jìn)入等待隊(duì)列之間不會(huì)被其它線程打斷。
以下是線程調(diào)用pthread_cond_wait的過(guò)程

  1. 線程必須已經(jīng)持有鎖:在調(diào)用pthread_cond_wait時(shí),線程必須已經(jīng)鎖定了某個(gè)互斥鎖,這是該函數(shù)的前提條件

  2. 自動(dòng)釋放互斥鎖:當(dāng)線程調(diào)用pthread_cond_wait時(shí),它會(huì)自動(dòng)釋放它當(dāng)前持有的互斥鎖。這一步是為了允許其它線程有機(jī)會(huì)獲取該互斥鎖并修改共享資源,從而可能改變條件變量的狀態(tài)

  3. 加入等待隊(duì)列:釋放互斥鎖之后,線程會(huì)接著被添加到條件變量的等待隊(duì)列中,并在此處等待

  4. 等待被喚醒:線程在等待隊(duì)列中等待,直到其它線程調(diào)用pthread_cond_signal 或 pthread_cond_broadcast來(lái)喚醒它

  5. 重新獲取互斥鎖:當(dāng)線程被喚醒時(shí),線程會(huì)嘗試重新獲取之前釋放的互斥鎖。如果鎖此時(shí)沒(méi)有被其它線程持有,線程將成功獲取鎖并繼續(xù)執(zhí)行。如果鎖仍然被其它線程持有,線程將阻塞(在申請(qǐng)鎖的地方阻塞),直到能夠獲取鎖時(shí)。

具體來(lái)說(shuō),pthread_cond_wait函數(shù)的內(nèi)部實(shí)現(xiàn)保證了2,3步驟的原子性。


偽喚醒問(wèn)題的解決 (if->while)

偽喚醒問(wèn)題是指:在多線程環(huán)境中,當(dāng)線程等待某個(gè)條件變量時(shí),它可能會(huì)在沒(méi)有到達(dá)預(yù)期的情況下被喚醒。
對(duì)于這一問(wèn)題,我們可以在判斷的時(shí)候,將if 變?yōu)?while,使其被喚醒后任然進(jìn)行條件判斷,如果條件滿足,線程繼續(xù)向后執(zhí)行,如果條件不被滿足,線程繼續(xù)在該條件變量下等待。

pthread_mutex_lock(&mutex);
// 訪問(wèn)臨界區(qū) 
while(條件為假)
	pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock(&mutex);

總結(jié)

以上就是我對(duì)于線程同步的總結(jié)。

linux:線程同步,Linux,linux,運(yùn)維文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-854918.html

到了這里,關(guān)于linux:線程同步的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Linux和windows進(jìn)程同步與線程同步那些事兒(五):Linux下進(jìn)程同步

    Linux和windows進(jìn)程同步與線程同步那些事兒(一) Linux和windows進(jìn)程同步與線程同步那些事兒(二): windows線程同步詳解示例 Linux和windows進(jìn)程同步與線程同步那些事兒(三): Linux線程同步詳解示例 Linux和windows進(jìn)程同步與線程同步那些事兒(四):windows 下進(jìn)程同步 Linux和wi

    2024年02月02日
    瀏覽(27)
  • Linux--線程-條件控制實(shí)現(xiàn)線程的同步

    Linux--線程-條件控制實(shí)現(xiàn)線程的同步

    1.條件變量 條件變量是線程另一可用的同步機(jī)制。條件變量給多個(gè)線程提供了一個(gè)會(huì)合的場(chǎng)所。條件變量與互斥量一起使用時(shí),允許線程以無(wú)競(jìng)爭(zhēng)的方式等待特定的條件發(fā)生。 條件本身是由互斥量保護(hù)的。線程在改變條件狀態(tài)前必須首先鎖住互斥量,其他線程在獲得互斥量之

    2024年02月05日
    瀏覽(23)
  • 【Linux】線程同步和互斥

    【Linux】線程同步和互斥

    1.臨界資源:多線程執(zhí)行流共享的資源,且一次只能允許一個(gè)執(zhí)行流訪問(wèn)的資源就叫做臨界資源。(多線程、多進(jìn)程打印數(shù)據(jù)) 2.臨界區(qū):每個(gè)線程內(nèi)部,訪問(wèn)臨界資源的代碼,就叫做臨界區(qū)。 3.互斥:任何時(shí)刻,互斥保證有且只有一個(gè)執(zhí)行流進(jìn)入臨界區(qū),訪問(wèn)臨界資源,通常對(duì)

    2024年02月08日
    瀏覽(27)
  • 【Linux】線程同步

    【Linux】線程同步

    初始化條件變量-pthread_cond_init 初始化條件變量的函數(shù)叫做 pthread_cond_init 參數(shù)說(shuō)明 cond:需要初始化的條件變量 attr:初始化條件變量的屬性,一般設(shè)置為NULL 返回值說(shuō)明 初始化成功返回0,失敗返回錯(cuò)誤碼 注意:調(diào)用 pthread_cond_init 函數(shù)初始化條件變量叫做動(dòng)態(tài)分配,我們還可以用靜

    2024年02月07日
    瀏覽(19)
  • Linux線程同步實(shí)例

    Linux線程同步實(shí)例

    生產(chǎn)者消費(fèi)者模型是一種常用的并發(fā)設(shè)計(jì)模式,它可以解決生產(chǎn)者和消費(fèi)者之間的速度不匹配、解耦、異步等問(wèn)題。生產(chǎn)者消費(fèi)者模型的應(yīng)用場(chǎng)景有很多,例如Excutor任務(wù)執(zhí)行框架、消息中間件activeMQ、任務(wù)的處理時(shí)間比較長(zhǎng)的情況下等。 生產(chǎn)者消費(fèi)者模型的基本結(jié)構(gòu)如下 :

    2024年02月07日
    瀏覽(20)
  • Linux->線程同步

    Linux->線程同步

    前言: 1 線程同步引入 2 條件變量 2.1 線程饑餓 2.2 條件變量接口 2.3 添加條件變量 3 生產(chǎn)者和消費(fèi)者模型 ? ? ? ? 本篇主要講解了關(guān)于線程同步的相關(guān)知識(shí),還有生產(chǎn)者和消費(fèi)者模型的認(rèn)識(shí)和使用。 ? ? ? ? 在講解線程同步之前,我們先來(lái)看一下當(dāng)一個(gè)程序之中只有線程互

    2024年02月11日
    瀏覽(20)
  • linux:線程同步

    linux:線程同步

    個(gè)人主頁(yè) : 個(gè)人主頁(yè) 個(gè)人專欄 : 《數(shù)據(jù)結(jié)構(gòu)》 《C語(yǔ)言》《C++》《Linux》 本文作為我對(duì)于線程同步知識(shí)總結(jié) 同步:在保證數(shù)據(jù)安全的前提下,讓線程能夠按照某種順序訪問(wèn)臨界資源,從而有效避免饑餓問(wèn)題,叫做同步 競(jìng)態(tài)條件:是指多個(gè)線程同時(shí)訪問(wèn)系統(tǒng)共享資源時(shí),由

    2024年04月17日
    瀏覽(17)
  • 【Linux】多線程2——線程互斥與同步/多線程應(yīng)用

    【Linux】多線程2——線程互斥與同步/多線程應(yīng)用

    ??上文主要介紹了多線程之間的獨(dú)立資源,本文將詳細(xì)介紹多線程之間的 共享資源 存在的問(wèn)題和解決方法。 intro 多線程共享進(jìn)程地址空間,包括創(chuàng)建的全局變量、堆、動(dòng)態(tài)庫(kù)等。下面是基于全局變量實(shí)現(xiàn)的一個(gè)多線程搶票的demo。 發(fā)現(xiàn)錯(cuò)誤:線程搶到負(fù)數(shù)編號(hào)的票,為什么

    2024年02月10日
    瀏覽(20)
  • Linux-線程的同步與互斥

    Linux-線程的同步與互斥

    ?? 臨界資源:多線程指行流共享的資源叫做臨界資源。 ?? 臨界區(qū):每個(gè)線程內(nèi)部訪問(wèn)臨界資源的代碼片段叫做臨界區(qū)。 ?? 互斥:任何時(shí)刻,互斥保證只有一個(gè)指行流進(jìn)入臨界區(qū),訪問(wèn)臨界資源,通常是對(duì)臨界區(qū)起保護(hù)作用。 ?? 原子性:不被任何調(diào)度所打斷的操作,該

    2024年02月09日
    瀏覽(19)
  • Linux——多線程,互斥與同步

    Linux——多線程,互斥與同步

    目錄 一.linux互斥 1.進(jìn)程線程間的互斥相關(guān)背景概念 2.互斥量mutex 3.加鎖互斥鎖mutex 4.鎖的底層原理 ?二.可重入VS線程安全 1.概念 2.常見(jiàn)的線程不安全的情況 3.常見(jiàn)的線程安全的情況? 4.常見(jiàn)不可重入的情況? 5..常見(jiàn)可重入的情況 6.可重入與線程安全聯(lián)系 ?三.死鎖 1.死鎖四個(gè)必

    2024年02月05日
    瀏覽(20)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包