欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++中關(guān)于互斥量的全面認(rèn)知

 更新時(shí)間:2022年05月09日 11:10:45   作者:Gy648  
線程的主要優(yōu)勢(shì)在于,能夠通過(guò)全局變量來(lái)共享信息。不過(guò),這種便捷的共享是有代價(jià)的:必須確保多個(gè)線程不會(huì)同時(shí)修改同一變量,或者某一線程不會(huì)讀取正由其他線程修改的變量。為了防止出現(xiàn)線程某甲試圖訪?問(wèn)一共享變量時(shí),線程某乙正在對(duì)其進(jìn)行修改。引入了互斥量

互斥量(保護(hù)對(duì)共享變量的訪問(wèn))

1.概念

互斥(mutex)是防止同時(shí)訪問(wèn)共享資源的程序?qū)ο蟆?/p>

為避免線程更新共享變量時(shí)所出現(xiàn)問(wèn)題,必須使用互斥量( mutex 是 mutual exclusion 的 縮寫)來(lái)確保同時(shí)僅有一個(gè)線程可以訪問(wèn)某項(xiàng)共享資源。 即就是 使用互斥量來(lái)實(shí)現(xiàn)原子訪問(wèn)操作

2.狀態(tài)

已鎖定( locked)和未鎖定( unlocked)。任何時(shí)候,至多只有一個(gè)線程可以鎖定該互斥量。試圖對(duì)已經(jīng)鎖定的某一互斥量再次加鎖,將可能阻塞線程或者報(bào)錯(cuò)失敗,具體取決于加鎖時(shí)使用的方法

3.特點(diǎn)

一旦線程鎖定互斥量,隨即成為該互斥量的所有者。只有所有者才能給互斥量解鎖。因?yàn)樗袡?quán)的關(guān)系,有時(shí)會(huì)使用術(shù)語(yǔ)獲?。?acquire)和釋放( release)來(lái)替代加鎖和解鎖。

互斥量的分配

互斥量既可以像靜態(tài)變量那樣分配,也可以在運(yùn)行時(shí)動(dòng)態(tài)創(chuàng)建

1.靜態(tài)分配

互斥量是屬于 pthread_mutex_t 類型的變量

在使用之前必須對(duì)其初始化。

pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER

2.動(dòng)態(tài)分配

#include<pthread.h>

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

參數(shù) mutex 指定函數(shù)執(zhí)行初始化操作的目標(biāo)互斥量。

參數(shù) attr 是指向 pthread_mutexattr_t 類型對(duì)象的指針,該對(duì)象在函數(shù)調(diào)用之前已經(jīng)過(guò)了初始化處理,用于定義互斥量的屬性。若將 attr 參數(shù)置為 NULL,則該互斥量的各種屬性會(huì)取默認(rèn)值。

注:

  • 初始化一個(gè)業(yè)已初始化的互斥量將導(dǎo)致未定義的行為
  • 動(dòng)態(tài)分配于堆中的互斥量。例如,動(dòng)態(tài)創(chuàng)建針對(duì)某一結(jié)構(gòu)的鏈表,表中每個(gè)結(jié)構(gòu)都包含一個(gè) pthread_mutex_t 類型的字段來(lái)存放互斥量,借以保護(hù)對(duì)該結(jié)構(gòu)的訪問(wèn)。
  • 互斥量是在棧中分配的自動(dòng)變量。
  • 初始化經(jīng)由靜態(tài)分配,且不使用默認(rèn)屬性的互斥量。

加鎖和解鎖互斥量

初始化之后,互斥量處于未鎖定狀態(tài)。函數(shù) pthread_mutex_lock()可以鎖定某一互斥量,而函數(shù) pthread_mutex_unlock()則可以將一個(gè)互斥量解鎖。

函數(shù)原型

int pthread_mutex_lock(pthread_mutex_t *mutex);

int pthread_mutex_trylock(pthread_mutex_t *mutex);

int pthread_mutex_unlock(pthread_mutex_t *mutex);

int pthread_mutex_timedlock(pthread_mutex_t *restrict mutex, const struct timespec *restrict abs_timeout);

1.創(chuàng)建互斥鎖

pthread_mutex_t mtx;

互斥鎖的類型是 pthread_mutex_t ,所以定義一個(gè)變量就是創(chuàng)建了一個(gè)互斥鎖:

2.初始化互斥鎖

//第二個(gè)參數(shù)為 NULL,互斥鎖的屬性會(huì)設(shè)置為默認(rèn)屬性
pthread_mutex_init(&mtx, NULL);

3.獲取互斥鎖

在進(jìn)行互斥操作的時(shí)候, 應(yīng)該先"拿到鎖"再執(zhí)行需要互斥的操作,否則可能會(huì)導(dǎo)致多個(gè)線程都需要訪問(wèn)的數(shù)據(jù)結(jié)果不一致。

4.阻塞調(diào)用

pthread_mutex_lock(&mtx);

5.非阻塞調(diào)用

如果鎖被占用就不用,如果沒(méi)被占用那就用, 可以使用 pthread_mutex_trylock() 函數(shù)。 用法和pthread_mutex_lock() 用法類似,不過(guò)當(dāng)請(qǐng)求的鎖正在被占用的時(shí)候, 不會(huì)進(jìn)入阻塞狀態(tài),而是立刻返回,并返回一個(gè)錯(cuò)誤代碼 EBUSY,意思是說(shuō), 有其它線程正在使用這個(gè)鎖。

int err = pthread_mutex_trylock(&mtx);
if(0 != err) {
    if(EBUSY == err) {
        //The mutex could not be acquired because it was already locked.
    }
}

6.超時(shí)調(diào)用

如果不想不斷的調(diào)用 pthread_mutex_trylock() 來(lái)測(cè)試互斥鎖是否可用, 而是想阻塞調(diào)用,但是增加一個(gè)超時(shí)時(shí)間, 用pthread_mutex_timedlock() 解決, 其調(diào)用方式如下:

struct timespec abs_timeout;
abs_timeout.tv_sec = time(NULL) + 1;
abs_timeout.tv_nsec = 0;
int err = pthread_mutex_timedlock(&mtx, &abs_timeout);
if(0 != err) {
    if(ETIMEDOUT == err) {
        //The mutex could not be locked before the specified timeout expired.
    }
}

阻塞等待,但是只等待一秒鐘,后如果還沒(méi)拿到鎖的話, 那就返回,并返回一個(gè)錯(cuò)誤代碼 ETIMEDOUT,意思是超時(shí)了。

其中 timespec 定義在頭文件 time.h 中,其定義如下

struct timespec
{
    __time_t tv_sec;        /* Seconds.  */
    long int tv_nsec;       /* Nanoseconds.  */
};

這個(gè)函數(shù)里面的時(shí)間,是絕對(duì)時(shí)間,所以這里用 time() 函數(shù)返回的時(shí)間增加了 1 秒

7.釋放互斥鎖

用完互斥鎖,一定要記得釋放,下一個(gè)想要獲得這個(gè)鎖的線程, 只能去等。

釋放互斥鎖比較簡(jiǎn)單,使用 pthread_mutex_unlock() 即可:

pthread_mutex_unlock(&mtx);

8.銷毀線程鎖

pthread_mutex_destroy(&mtx)

一個(gè)被銷毀的線程鎖可以被 pthread_mutex_init() 再次初始化。對(duì)被銷毀的線程鎖進(jìn)行其它操作,其結(jié)果是未定義的。

對(duì)一個(gè)處于已初始化但未鎖定狀態(tài)的線程鎖進(jìn)行銷毀是安全的。盡量避免對(duì)一個(gè)處于鎖定狀態(tài)的線程鎖進(jìn)行銷毀操作。

互斥量的死鎖

當(dāng)超過(guò)一個(gè)線程加鎖同一組互斥量時(shí),就有可能發(fā)生死鎖。

例,每個(gè)線程都成功地鎖住一個(gè)互斥量,接著試圖對(duì)已為另一線程鎖定的互斥量加鎖。

兩個(gè)線程將無(wú)限期等待

有兩種解決方法

1.當(dāng)多個(gè)線程對(duì)一組互斥量操作時(shí),總是應(yīng)該以相同順序?qū)υ摻M互斥量進(jìn)行鎖定,如果兩個(gè)線程總是先鎖定 mutex1 再鎖定 mutex2,死鎖就不會(huì)出現(xiàn)

2.使用頻率較低,就是“嘗試一下,然后恢復(fù)”,在這種方案中,線程先使用函數(shù)pthread_mutex_lock()鎖定第 1 個(gè)互斥量,然后使用函數(shù)pthread_mutex_trylock()來(lái)鎖定其余互斥量。如果任一pthread_mutex_trylock()調(diào)用失?。ǚ祷?EBUSY),那么該線程將釋放所有 互斥量,也許經(jīng)過(guò)一段時(shí)間間隔,從頭再試

注:

  • 對(duì)共享資源操作前一定要獲得鎖。
  • 完成操作以后一定要釋放鎖。
  • 盡量短時(shí)間地占用鎖。
  • 如果有多鎖, 如獲得順序是ABC連環(huán)扣, 釋放順序也應(yīng)該是ABC。
  • 線程錯(cuò)誤返回時(shí)應(yīng)該釋放它所獲得的鎖。

例子

保護(hù)fp指向文件中數(shù)的累加正常進(jìn)行

static pthread_mutex_t mut=PTHREAD_MUTEX_INITIALIZER;
void *thr_prime(void *p)
{
    FILE *fp;
    char linebuf[linesize];
    fp =fopen(fname,"r+");   //多個(gè)線程之間相撞拿到 同一個(gè)fp 開(kāi)始覆蓋寫操作
    if(fp == NULL)  
    {
        perror("fopen");
        exit(-1);
    }
    //加鎖
    pthread_mutex_lock(&mut);
    fgets(linebuf,linesize,fp);
    fseek(fp,0,SEEK_SET);
    fprintf(fp,"%d\n",atoi(linebuf)+1);
    //解鎖
    pthread_mutex_unlock(&mut);
    fclose(fp);
    pthread_exit(NULL);
}
int main()
{
    int err,i;
    pthread_t tid[thrnum];
    //main 線程 進(jìn)行創(chuàng)建線程
    for(i=0 ; i<=thrnum ;i++)
    {
        err =pthread_create(tid + i ,NULL,thr_prime,NULL);
        if(err)
        {
            fprintf(stderr,"pthread_creat():%s\n",strerror(err));
            exit(1);
        }
    }
    //為線程收尸
    for(i =0 ; i<=thrnum ;i++)
    {
        pthread_join(tid[i],NULL);
    }
    pthread_mutex_destroy(&mut);
    exit(0);
}

到此這篇關(guān)于C++中關(guān)于互斥量的全面認(rèn)知的文章就介紹到這了,更多相關(guān)C++互斥量?jī)?nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++中的命名空間詳細(xì)介紹

    C++中的命名空間詳細(xì)介紹

    大家好,本篇文章主要講的是C++中的命名空間詳細(xì)介紹,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下
    2022-02-02
  • C語(yǔ)言實(shí)現(xiàn)賓館管理系統(tǒng)課程設(shè)計(jì)

    C語(yǔ)言實(shí)現(xiàn)賓館管理系統(tǒng)課程設(shè)計(jì)

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)賓館管理系統(tǒng)課程設(shè)計(jì),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • 深入理解C預(yù)處理器

    深入理解C預(yù)處理器

    下面小編就為大家?guī)?lái)一篇深入理解C預(yù)處理器。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-08-08
  • C++中vector與remove()函數(shù)詳解

    C++中vector與remove()函數(shù)詳解

    這篇文章主要介紹了C++中vector與remove()函數(shù),本文實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-06-06
  • C語(yǔ)言經(jīng)典順序表真題演練講解

    C語(yǔ)言經(jīng)典順序表真題演練講解

    程序中經(jīng)常需要將一組數(shù)據(jù)元素作為整體管理和使用,需要?jiǎng)?chuàng)建這種元素組,用變量記錄它們,傳進(jìn)傳出函數(shù)等。一組數(shù)據(jù)中包含的元素個(gè)數(shù)可能發(fā)生變化,順序表則是將元素順序地存放在一塊連續(xù)的存儲(chǔ)區(qū)里,元素間的順序關(guān)系由它們的存儲(chǔ)順序自然表示
    2022-04-04
  • 淺談C++左值引用和右值引用

    淺談C++左值引用和右值引用

    下面小編就為大家?guī)?lái)一篇淺談C++左值引用和右值引用。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-01-01
  • 基于Matlab制作一款簡(jiǎn)單的龍舟小游戲

    基于Matlab制作一款簡(jiǎn)單的龍舟小游戲

    這篇文章主要為大家介紹如何利用Matlab制作一款簡(jiǎn)單的龍舟小游戲,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Matlab有一定幫助,需要的可以參考一下
    2022-03-03
  • C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單的<三子棋>案例

    C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單的<三子棋>案例

    這篇文章主要介紹了C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單的《三子棋》,本文通過(guò)功能區(qū)分一步步實(shí)現(xiàn)該案例,通過(guò)逐步的解析和代碼列舉,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • c++實(shí)現(xiàn)合并文件以及拆分實(shí)例代碼

    c++實(shí)現(xiàn)合并文件以及拆分實(shí)例代碼

    這篇文章主要介紹了c++實(shí)現(xiàn)合并文件以及拆分實(shí)例代碼,小編覺(jué)得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下
    2018-01-01
  • C語(yǔ)言SetConsoleCursorInfo函數(shù)使用方法

    C語(yǔ)言SetConsoleCursorInfo函數(shù)使用方法

    這篇文章介紹了C語(yǔ)言SetConsoleCursorInfo函數(shù)的使用方法,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-12-12

最新評(píng)論