C++中的多線程

c++線程中的幾種鎖

  • 在代碼中使用pthread沉帮,進(jìn)行編譯時(shí),需要使用命令 g++ -o hello hello.c -lpthread
  • Makefile怎么寫鞍盗?

互斥鎖

互斥鎖只有兩種狀態(tài)随橘,鎖定非鎖定

頭文件:<pthread.h>
類型:pthread_mutex_t

  • pthread_mutex_lock:加鎖还栓。如果鎖已經(jīng)被占有,則該線程加入一個(gè)隊(duì)列中。
  • pthread_mutex_trylock:嘗試加鎖背传,如果鎖已被占有呆瞻,則線程不加入隊(duì)列,而是返回錯(cuò)誤径玖。
  • pthread_mutex_unlock:釋放鎖

Linux c++ 多線程編程基礎(chǔ)——互斥鎖

例程

  • 5個(gè)線程互斥顯示數(shù)組數(shù)字痴脾,當(dāng)其中一個(gè)線程在顯示時(shí),其他線程無(wú)法顯示梳星,直接退出
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>

// 聲明并且初始化鎖(互斥鎖)
pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
 
int tf[5];
 
void* print(void* i)
{
    /********************************************
    * 如果改為 int flag = pthread_mutex_lock(&mut); 
    * 則為阻塞的,該線程會(huì)被加入隊(duì)列等待開鎖 
    ********************************************/

    /**************************************************
    * 非阻塞如果不為零說明有其他線程正在進(jìn)行,即不應(yīng)該執(zhí)行該線程
    * 因此可以判斷flag并退出該線程
    **************************************************/
    int *id = (int*)i;

    int flag = pthread_mutex_trylock(&mut);
    if (flag==0)
    {
        sleep(1);
        for (int j=0;j<5;j++)
            printf("thread %d: %d\n", *id, j);
        pthread_mutex_unlock(&mut);
    }
    else
    {
        printf("thread %d: 其他線程正在進(jìn)行\(zhòng)n", *id);
    }
}

int main()
{
    pthread_t td[5]; // 初始化線程
    for(int i=0;i<5;i++)
        tf[i] = i;
    for(int i=0;i<5;i++)
        // 創(chuàng)建線程
        pthread_create(&td[i],NULL,print,(void *)&tf[i]);
    for(int i=0;i<5;i++)
    {
        // 運(yùn)行線程,join函數(shù)確保子線程執(zhí)行完了主程序才退出
        pthread_join(td[i],NULL);
    }
    pthread_mutex_destroy(&mut);
}

條件鎖

條件鎖就是所謂的條件變量赞赖,某一個(gè)線程因?yàn)槟硞€(gè)條件為滿足時(shí)可以使用條件變量使改程序處于阻塞狀態(tài)。一旦條件滿足以“信號(hào)量”的方式喚醒一個(gè)因?yàn)樵摋l件而被阻塞的線程冤灾。

頭文件:<pthread.h>
類型:pthread_cond_t

  • pthread_cond_wait:線程阻塞在條件變量
  • pthread_cond_signal:線程被喚醒

linux C++ 多線程使用pthread_cond 條件變量
線程屬性pthread_attr_t簡(jiǎn)介

例程

  • 線程0前域、線程1互斥加一個(gè)數(shù),加一次喚醒一次條件觸發(fā)的線程2韵吨,如果線程2處于阻塞等待狀態(tài)則被喚醒
  • 線程2判斷數(shù)值大小時(shí)匿垄,給線程0、1上鎖归粉,停止加數(shù)年堆,當(dāng)數(shù)字小于10時(shí),等待3秒盏浇,否則加100退出該線程
  • 線程0变丧、1各加10次退出線程,線程2檢測(cè)到數(shù)字大于10加100后退出線程绢掰,三個(gè)線程都結(jié)束程序退出
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>

#define NUM_THREADS 3 
#define TCOUNT      10 
#define COUNT_LIMIT 10 

int count = 0;
int thread_ids[3] = {0,1,2};
pthread_mutex_t count_mutex;  // 計(jì)數(shù)時(shí)上鎖
pthread_cond_t  count_threshold_cv;

void *inc_count(void *idp)
{
    int i = 0;
    int taskid = 0;
    int *my_id = (int*)idp;

    for (i=0; i<TCOUNT; i++) {
        // 互斥鎖上鎖
        pthread_mutex_lock(&count_mutex);
        taskid = count;
        count++;

        /*
          喚醒一個(gè)阻塞在該條件變量的線程
          如果沒有線程被阻塞在條件變量上痒蓬,那么調(diào)用pthread_cond_signal()將沒有作用
        */
        pthread_cond_signal(&count_threshold_cv);

        printf("inc_count(): thread %d, count = %d, 開互斥鎖\n", *my_id, count);
        // 互斥鎖解鎖
        pthread_mutex_unlock(&count_mutex);
        sleep(1);
    }
    printf("inc_count(): thread %d, Threshold reached.\n", *my_id);

    pthread_exit(NULL);
}

void *watch_count(void *idp)
{
    int *my_id = (int*)idp;
    printf("Starting watch_count(): thread %d\n", *my_id);

    pthread_mutex_lock(&count_mutex);
    while(count<COUNT_LIMIT) {
        sleep(3); 
        /*
          函數(shù)將自動(dòng)/原子到解鎖mutex參數(shù)指向的互斥鎖,
          并使當(dāng)前線程阻塞在cv參數(shù)指向的條件變量上
          被阻塞的線程可以被pthread_cond_signal函數(shù)滴劲,
          pthread_cond_broadcast函數(shù)喚醒攻晒,
          也可能在被信號(hào)中斷后被喚醒
          pthread_cond_wait函數(shù)的返回并不意味著條件的值一定發(fā)生了變化,
          必須重新檢查條件的值. 
          本例子中使用類COUNT_LIMIT最為滿足條件的值
          pthread_cond_wait函數(shù)返回時(shí)班挖,相應(yīng)的互斥鎖將被當(dāng)前線程鎖定鲁捏,
          即使是函數(shù)出錯(cuò)返回
        */
        pthread_cond_wait(&count_threshold_cv, &count_mutex);
        printf("watch_count(): thread %d 收到條件信號(hào).\n", *my_id);
    }

    count += 100;
    pthread_mutex_unlock(&count_mutex);
    pthread_exit(NULL);
}

int main (int argc, char *argv[])
{
    int i, rc;
    pthread_t threads[3];
    pthread_attr_t attr; // 線程屬性

    /* Initialize mutex and condition variable objects */
    pthread_mutex_init(&count_mutex, NULL);
    pthread_cond_init (&count_threshold_cv, NULL);

    /* For portability, explicitly create threads in a joinable state */
    pthread_attr_init(&attr);  // 對(duì)線程屬性變量的初始化
    /*
    設(shè)置線程detachstate屬性。該表示新線程是否與進(jìn)程中其他線程脫離同步萧芙,
    如果設(shè)置為PTHREAD_CREATE_DETACHED則新線程不能用pthread_join()來同步给梅,
    且在退出時(shí)自行釋放所占用的資源。缺省為PTHREAD_CREATE_JOINABLE狀態(tài)双揪。
    這個(gè)屬性也可以在線程創(chuàng)建并運(yùn)行以后用pthread_detach()來設(shè)置动羽,
    而一旦設(shè)置為PTHREAD_CREATE_DETACH狀態(tài)(不論是創(chuàng)建時(shí)設(shè)置還是運(yùn)行時(shí)設(shè)置)
    則不能再恢復(fù)到PTHREAD_CREATE_JOINABLE狀態(tài)。
    */
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
    pthread_create(&threads[0], &attr, inc_count,   (void *)&thread_ids[0]);
    pthread_create(&threads[1], &attr, inc_count,   (void *)&thread_ids[1]);
    pthread_create(&threads[2], &attr, watch_count, (void *)&thread_ids[2]);

    /* Wait for all threads to complete */
    for (i=0; i<NUM_THREADS; i++) {
        pthread_join(threads[i], NULL);
    }
    printf ("Main(): Waited on %d  threads. Done.\n", NUM_THREADS);

    /* Clean up and exit */
    pthread_attr_destroy(&attr);
    pthread_mutex_destroy(&count_mutex);
    pthread_cond_destroy(&count_threshold_cv);
    pthread_exit(NULL);

    return 0;
}

自旋鎖

當(dāng)發(fā)生阻塞時(shí)渔期,互斥鎖可以讓CPU去處理其他的任務(wù)运吓;而自旋鎖讓CPU一直不斷循環(huán)請(qǐng)求獲取這個(gè)鎖渴邦,它會(huì)一直占用CPU請(qǐng)求這個(gè)自旋鎖使得CPU不能去做其他的事情,直到獲取這個(gè)鎖為止拘哨,比較耗費(fèi)CPU

頭文件:<pthread.h>
類型:pthread_spinlock_t

  • 初始化:pthread_spin_init(pthread_spinlock_t *__lock, int __pshared);
  • pthread_spin_lock(x); //只有在獲得鎖的情況下才返回谋梭,否則一直“自旋”
  • pthread_spin_trylock(x); //如果該鎖已經(jīng)被爭(zhēng)用,那么該函數(shù)立即返回一個(gè)非0值倦青,而不會(huì)自旋等待鎖被釋放;
  • 釋放鎖:phtread_spin_unlock(x);
  • 釋放資源:pthread_spin_destroy(&lock);

注意:自旋鎖適合于短時(shí)間的的輕量級(jí)的加鎖機(jī)制

代碼同互斥鎖瓮床,更改init、lock姨夹、unlock纤垂、destroy即可

...保持更新中

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市磷账,隨后出現(xiàn)的幾起案子峭沦,更是在濱河造成了極大的恐慌,老刑警劉巖逃糟,帶你破解...
    沈念sama閱讀 217,657評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件吼鱼,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡绰咽,警方通過查閱死者的電腦和手機(jī)菇肃,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來取募,“玉大人琐谤,你說我怎么就攤上這事⊥婷簦” “怎么了斗忌?”我有些...
    開封第一講書人閱讀 164,057評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)旺聚。 經(jīng)常有香客問我织阳,道長(zhǎng),這世上最難降的妖魔是什么砰粹? 我笑而不...
    開封第一講書人閱讀 58,509評(píng)論 1 293
  • 正文 為了忘掉前任唧躲,我火速辦了婚禮,結(jié)果婚禮上碱璃,老公的妹妹穿的比我還像新娘弄痹。我一直安慰自己,他們只是感情好厘贼,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,562評(píng)論 6 392
  • 文/花漫 我一把揭開白布界酒。 她就那樣靜靜地躺著,像睡著了一般嘴秸。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,443評(píng)論 1 302
  • 那天岳掐,我揣著相機(jī)與錄音凭疮,去河邊找鬼。 笑死串述,一個(gè)胖子當(dāng)著我的面吹牛执解,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播纲酗,決...
    沈念sama閱讀 40,251評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼衰腌,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了觅赊?” 一聲冷哼從身側(cè)響起右蕊,我...
    開封第一講書人閱讀 39,129評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎吮螺,沒想到半個(gè)月后饶囚,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,561評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡鸠补,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,779評(píng)論 3 335
  • 正文 我和宋清朗相戀三年萝风,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片紫岩。...
    茶點(diǎn)故事閱讀 39,902評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡规惰,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出泉蝌,到底是詐尸還是另有隱情歇万,我是刑警寧澤,帶...
    沈念sama閱讀 35,621評(píng)論 5 345
  • 正文 年R本政府宣布梨与,位于F島的核電站堕花,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏粥鞋。R本人自食惡果不足惜缘挽,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,220評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望呻粹。 院中可真熱鬧壕曼,春花似錦、人聲如沸等浊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)筹燕。三九已至轧飞,卻和暖如春衅鹿,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背过咬。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工大渤, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人掸绞。 一個(gè)月前我還...
    沈念sama閱讀 48,025評(píng)論 2 370
  • 正文 我出身青樓泵三,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親衔掸。 傳聞我的和親對(duì)象是個(gè)殘疾皇子烫幕,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,843評(píng)論 2 354

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