色偷偷91综合久久噜噜-色偷偷成人-色偷偷尼玛图亚洲综合-色偷偷人人澡久久天天-国内精品视频一区-国内精品视频一区二区三区

Hello! 歡迎來到小浪云!


【linux學習指南】線程同步與互斥


avatar
小浪云 2025-04-17 44

?線程互斥? 庫函數(shù)strncpy?進程線程間的互斥相關背景概念臨界資源:多線程執(zhí)?流共享的資源就叫做臨界資源臨界區(qū):每個線程內(nèi)部,訪問臨界資源的代碼,就叫做臨界區(qū)互斥:任何時刻,互斥保證有且只有?個執(zhí)?流進?臨界區(qū),訪問臨界資源,通常對臨界資源起保護作?原?性(后?討論如何實現(xiàn)):不會被任何調(diào)度機制打斷的操作,該操作只有兩態(tài),要么完成,要么未完成?互斥量mutex?部分情況,線程使?的數(shù)據(jù)都是局部變量,變量的地址空間在線程空間內(nèi),這種情況,變量歸屬單個線程,其他線程?法獲得這種變量。但有時候,很多變量都需要在線程間共享,這樣的變量稱為共享變量,可以通過數(shù)據(jù)的共享,完成線程之間的交互。多個線程并發(fā)的操作共享變量,會帶來?些問題。

makefile文件

代碼語言:JavaScript代碼運行次數(shù):0運行復制

bin=ticketcc=g++src=$(wildcard *.cc)obj=$(src:.cc=.o)$(bin):$(obj)$(cc) -o $@ $^ -lpthread%.o:%.cc@echo "Comiling $<p>代碼:</p>代碼語言:javascript<i class="icon-code"></i>代碼運行次數(shù):<!-- -->0<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewbox="0 0 16 16" fill="none"><path d="M6.66666 10.9999L10.6667 7.99992L6.66666 4.99992V10.9999ZM7.99999 1.33325C4.31999 1.33325 1.33333 4.31992 1.33333 7.99992C1.33333 11.6799 4.31999 14.6666 7.99999 14.6666C11.68 14.6666 14.6667 11.6799 14.6667 7.99992C14.6667 4.31992 11.68 1.33325 7.99999 1.33325ZM7.99999 13.3333C5.05999 13.3333 2.66666 10.9399 2.66666 7.99992C2.66666 5.05992 5.05999 2.66659 7.99999 2.66659C10.94 2.66659 13.3333 5.05992 13.3333 7.99992C13.3333 10.9399 10.94 13.3333 7.99999 13.3333Z" fill="currentcolor"></path></svg>運行<svg width="16" height="16" viewbox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M4.5 15.5V3.5H14.5V15.5H4.5ZM12.5 5.5H6.5V13.5H12.5V5.5ZM9.5 2.5H3.5V12.5H1.5V0.5H11.5V2.5H9.5Z" fill="currentcolor"></path></svg>復制<pre class="prism-token token line-numbers javascript">#include <stdio.h>#include <string>#include <string.h>#include <pthread.h>#include <unistd.h>int ticket = 100;void* routine(void* args){    char *id = (char*)args;    // std::string id = static_cast<const char>(args);    while(1)    {        if(ticket &gt; 0)        {            usleep(10000);            printf("%s sells ticket:%dn", id, ticket);            ticket--;        }        else        {            break;        }    }    return NULLptr;}int main(void){    pthread_t t1, t2 , t3, t4;    pthread_create(&amp;t1, nullptr, routine, (void*)"thread 1");    pthread_create(&amp;t2, nullptr, routine, (void*)"thread 2");    pthread_create(&amp;t3, nullptr, routine, (void*)"thread 3");    pthread_create(&amp;t4, nullptr, routine, (void*)"thread 4");    pthread_join(t1, nullptr);    pthread_join(t2, nullptr);    pthread_join(t3, nullptr);    pthread_join(t4, nullptr);    return 0;}</const></unistd.h></pthread.h></string.h></string></stdio.h>
【linux學習指南】線程同步與互斥
【linux學習指南】線程同步與互斥
【linux學習指南】線程同步與互斥
【linux學習指南】線程同步與互斥

if語句判斷條件為真以后,代碼可以并發(fā)的切換到其他進程usleep這個模擬夜漫長業(yè)務的過程這個漫長的業(yè)務過程中,可能有多個線程會進入該代碼段–ticket操作本身就不是一個原子操作

取出ticket–部分的匯編代碼

代碼語言:javascript代碼運行次數(shù):0運行復制

objdump -d a.out &gt; test.objdump 152   40064b:   8b 05 e3 04 20 00     mov       0x2004e3(%rip),%eax 600b34 <ticket> 153   400651:   83 e8 01                 sub        $0x1,%eax154   400654:   89 05 da 04 20 00       mov%eax,0x2004da(%rip)  600b34 <ticket></ticket></ticket>

–操作并不是原子操作而是對應三條匯編指令:

load將共享變量體的從內(nèi)存加載到寄存器update更新寄存器里面的只執(zhí)行復議操作store:將新值從寄存器寫回共享變量ticket的內(nèi)存地址

要解決以上問題需要做到三點:

代碼必須要有互斥行為:當代碼進入臨界區(qū)執(zhí)行時,不允許其他進程進入該臨界區(qū)如果多個線程同時要求進入臨界區(qū)的代碼,并且臨界區(qū)沒有線程在執(zhí)行,那么只能一個線程進入該臨界區(qū)如果現(xiàn)場不在臨界區(qū)中執(zhí)行,那么該現(xiàn)場就不能阻止其他進程進入臨界區(qū)

要做到這三點,本身是上就是需要一把鎖,linux上提供這把鎖叫互斥量

【linux學習指南】線程同步與互斥

互斥量的接口 初始化互斥量的兩種方法

方法1:靜態(tài)分配代碼語言:javascript代碼運行次數(shù):0運行復制

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER 

?法2,動態(tài)分配: int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr); 參數(shù): mutex:要初始化的互斥量 attr:這是一個指向 pthread_mutexattr_t 類型對象指針,該類型用于定義互斥鎖的屬性。如果將其設置為 NULL

銷毀互斥量 銷毀互斥量需要注意:

使用PTHREAD_ MUTEX_ INITIALIZER初始化的互斥量不需要銷毀不要銷毀?個已經(jīng)加鎖的互斥量已經(jīng)銷毀的互斥量,要確保后?不會有線程再嘗試加鎖代碼語言:javascript代碼運行次數(shù):0運行復制

int pthread_mutex_destroy(pthread_mutex_t *mutex);

互斥量加鎖和解鎖

代碼語言:javascript代碼運行次數(shù):0運行復制

int pthread_mutex_lock(pthread_mutex_t *mutex);int pthread_mutex_unlock(pthread_mutex_t *mutex);返回值:成功返回o,失敗返回錯誤號

調(diào)用pthread_ lock時,可能會遇到以下情況:

互斥量處于未鎖狀態(tài),該函數(shù)會將互斥量鎖定,同時返回成功發(fā)起函數(shù)調(diào)用時,其他線程已經(jīng)鎖定互斥量,或者存在其他線程同時申請互斥量,但沒有競爭到互斥量,那么pthread_lock調(diào)用會陷入阻塞(執(zhí)行流被掛起),等待互斥量解鎖。

改進上面的售票系統(tǒng):

代碼語言:javascript代碼運行次數(shù):0運行復制

#include <stdio.h>#include <string>#include <string.h>#include <pthread.h>#include <unistd.h>int ticket = 100;pthread_mutex_t mutex;void* routine(void* args){    char *id = (char*)args;    // std::string id = static_cast<const char>(args);    while(1)    {        pthread_mutex_lock(&amp;mutex);        if(ticket &gt; 0)        {            usleep(1000);            printf("%s sells ticket:%dn", id, ticket);            ticket--;            pthread_mutex_unlock(&amp;mutex);        }        else        {            pthread_mutex_unlock(&amp;mutex);            break;        }    }    return nullptr;}int main(void){    pthread_t t1, t2 , t3, t4;    pthread_create(&amp;t1, nullptr, routine, (void*)"thread 1");    pthread_create(&amp;t2, nullptr, routine, (void*)"thread 2");    pthread_create(&amp;t3, nullptr, routine, (void*)"thread 3");    pthread_create(&amp;t4, nullptr, routine, (void*)"thread 4");    pthread_join(t1, nullptr);    pthread_join(t2, nullptr);    pthread_join(t3, nullptr);    pthread_join(t4, nullptr);    pthread_mutex_destroy(&amp;mutex);    return 0;}</const></unistd.h></pthread.h></string.h></string></stdio.h>
【linux學習指南】線程同步與互斥
【linux學習指南】線程同步與互斥

?線程同步?條件變量當?個線程互斥地訪問某個變量時,它可能發(fā)現(xiàn)在其它線程改變狀態(tài)之前,它什么也做不了。例如?個線程訪問隊列時,發(fā)現(xiàn)隊列為空,它只能等待,只到其它線程將?個節(jié)點添加到隊列中。這種情況就需要?到條件變量。?同步概念與競態(tài)條件同步:在保證數(shù)據(jù)安全的前提下,讓線程能夠按照某種特定的順序訪問臨界資源,從?有效避免饑餓問題,叫做同步競態(tài)條件:因為時序問題,?導致程序異常,我們稱之為競態(tài)條件。在線程場景下,這種問題也 不難理解? 條件變量函數(shù)

初始化

代碼語言:javascript代碼運行次數(shù):0運行復制

int pthread_cond_init(pthread_cond_t *restrict cond,   const pthread_condattr_t*restrict attr);

參數(shù): cond:要初始化的條件變量 attr: NULL

銷毀:

代碼語言:javascript代碼運行次數(shù):0運行復制

int pthread_cond_destroy(pthread_cond_t *cond)

等待條件滿?

代碼語言:javascript代碼運行次數(shù):0運行復制

int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrictmutex);參數(shù):cond:要在這個條件變量上等待mutex:互斥量,后面詳細解釋

喚醒等待

代碼語言:javascript代碼運行次數(shù):0運行復制

int pthread_cond_broadcast(pthread_cond_t *cond);int pthread_cond_signal(pthread_cond_t *cond);

簡單案例:

我們先使用PTHREAD_COND/MUTEX_INITIALIZER進行測試,對其他細節(jié)暫不追究然后將接口更改成為使用pthread_cond_init/pthread_cond_destroy的方式,方便后續(xù)進行封裝代碼語言:javascript代碼運行次數(shù):0運行復制

#include <iostream>#include <string.h>#include <unistd.h>#include <pthread.h>pthread_cond_t cond = PTHREAD_COND_INITIALIZER;pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;void* active(void* args){    std::string name = static_cast<const char>(args);    while(true)    {        pthread_mutex_lock(&amp;mutex);        pthread_cond_wait(&amp;cond, &amp;mutex);        std::cout<figure class=""><img src="https://img.php.cn/upload/article/001/503/042/174487358175324.jpg" alt="【Linux學習指南】線程同步與互斥"></figure></const></pthread.h></unistd.h></string.h></iostream>

相關閱讀

主站蜘蛛池模板: 亚洲一级片免费 | 日本一区二区三区不卡在线视频 | 免费精品精品国产欧美在线 | 欧美日本一区二区三区 | 国产日韩高清一区二区三区 | 美国特级a毛片免费网站 | 三级黄色高清视频 | 免费亚洲成人 | 国产精品第| 奇米色88欧美一区二区 | 另类激情网 | 国产码欧美日韩高清综合一区 | 800av在线免费观看 | 五月亚洲 | 亚洲国产成人久久一区www妖精 | 欧美精品国产第一区二区 | 美女拍拍拍免费视频观看 | 一级毛片免费不卡夜夜欢 | 久久这里一区二区精品 | 国产成人精品久久二区二区 | 日韩免费一区二区三区 | 国产精品九九九久久九九 | 狠狠色狠狠色综合婷婷tag | 日本大臿亚洲香蕉大片 | 免费在线观看黄色毛片 | 在线激情网站 | 天天天天干 | 国产色播 | 97人人模人人爽视频一区二区 | 欧美激情五月 | 黄色一级毛片免费 | 天天干天天舔天天操 | 亚州激情视频 | 九九久久久 | 一级毛片不卡片免费观看 | 嫩草成人国产精品 | 曰本黄色一级 | 99久久这里只精品国产免费 | 亚洲一区二区三区免费看 | 日本国产一区二区三区 | 久久精品高清视频 |