色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

詳細談談Linux中的多線程同步和互斥機制

dyquk4xk2p3d ? 來源:Linux兵工廠 ? 作者:Linux兵工廠 ? 2023-03-20 09:09 ? 次閱讀

同步和互斥

互斥:多線程中互斥是指多個線程訪問同一資源時同時只允許一個線程對其進行訪問,具有唯一性和排它性。但互斥無法限制訪問者對資源的訪問順序,即訪問是無序的;

同步:多線程同步是指在互斥的基礎上(大多數情況),通過其它機制實現訪問者對資源的有序訪問。在大多數情況下,同步已經實現了互斥,特別是所有寫入資源的情況必定是互斥的。少數情況是指可以允許多個訪問者同時訪問資源。

互斥鎖

在多任務操作系統中,同時運行的多個任務可能都需要使用同一種資源。為了同一時刻只允許一個任務訪問資源,需要用互斥鎖對資源進行保護。互斥鎖是一種簡單的加鎖的方法來控制對共享資源的訪問,互斥鎖只有兩種狀態,即上鎖( lock )和解鎖( unlock )。

互斥鎖操作基本流程

訪問共享資源前,對互斥鎖進行加鎖

完成加鎖后訪問共享資源

對共享資源完成訪問后,對互斥鎖進行解鎖

對互斥鎖進行加鎖后,任何其他試圖再次對互斥鎖加鎖的線程將會被阻塞,直到鎖被釋放

互斥鎖特性

原子性:互斥鎖是一個原子操作,操作系統保證如果一個線程鎖定了一個互斥鎖,那么其他線程在同一時間不會成功鎖定這個互斥鎖

唯一性:如果一個線程鎖定了一個互斥鎖,在它解除鎖之前,其他線程不可以鎖定這個互斥鎖

非忙等待:如果一個線程已經鎖定了一個互斥鎖,第二個線程又試圖去鎖定這個互斥鎖,則第二個線程將被掛起且不占用任何CPU資源,直到第一個線程解除對這個互斥鎖的鎖定為止,第二個線程則被喚醒并繼續執行,同時鎖定這個互斥鎖

示例

#include
#include
#include
#include
#include

char*pTestBuf=nullptr;//全局變量

/*定義互斥鎖*/
pthread_mutex_tmutex;

void*ThrTestMutex(void*p)
{
pthread_mutex_lock(&mutex);//加鎖
{
pTestBuf=(char*)p;
sleep(1);
}
pthread_mutex_unlock(&mutex);//解鎖
}

intmain()
{
/*初始化互斥量,默認屬性*/
pthread_mutex_init(&mutex,NULL);

/*創建兩個線程對共享資源訪問*/
pthread_ttid1,tid2;
pthread_create(&tid1,NULL,ThrTestMutex,(void*)"Thread1");
pthread_create(&tid2,NULL,ThrTestMutex,(void*)"Thread2");

/*等待線程結束*/
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);

/*銷毀互斥鎖*/
pthread_mutex_destroy(&mutex);

return0;
}

讀寫鎖

讀寫鎖允許更高的并行性,也叫共享互斥鎖。互斥量要么是加鎖狀態,要么就是解鎖狀態,而且一次只有一個線程可以對其加鎖。讀寫鎖可以有3種狀態:讀模式下加鎖狀態、寫模式加鎖狀態、不加鎖狀態。一次只有一個線程可以占有寫模式的讀寫鎖,但是多個線程可以同時占有讀模式的讀寫鎖,即允許多個線程讀但只允許一個線程寫。

當讀操作較多,寫操作較少時,可用讀寫鎖提高線程讀并發性

讀寫鎖特性

如果有線程讀數據,則允許其它線程執行讀操作,但不允許寫操作

如果有線程寫數據,則其它線程都不允許讀、寫操作

如果某線程申請了讀鎖,其它線程可以再申請讀鎖,但不能申請寫鎖

如果某線程申請了寫鎖,其它線程不能申請讀鎖,也不能申請寫鎖

讀寫鎖適合于對數據的讀次數比寫次數多得多的情況

讀寫鎖創建和銷毀

#include
intphtread_rwlock_init(pthread_rwlock_t*restrictrwlock,constpthread_rwlockattr_t*restrictattr);
intpthread_rwlock_destroy(pthread_rwlock_t*rwlock);

參數:rwlock:讀寫鎖,attr:讀寫鎖屬性

返回值:成功返回0,出錯返回錯誤碼

讀寫鎖加鎖解鎖

#include
/**加讀鎖*/
intpthread_rwlock_rdlock(pthread_rwlock_t*rwlock);
/**加寫鎖*/
intpthread_rwlock_wrlock(pthread_rwlock_t*rwlock);
/**釋放鎖*/
intpthread_rwlock_unlock(pthread_rwlock_t*rwlock);

參數:rwlock:讀寫鎖

返回值:成功返回 0;出錯,返回錯誤碼

示例

#include
#include
#include
#include
#include

/*定義讀寫鎖*/
pthread_rwlock_trwlock;

/*定義共享資源變量*/
intg_nNum=0;

/*讀操作其他線程允許讀操作不允許寫操作*/
void*fun1(void*arg)
{
while(1)
{
pthread_rwlock_rdlock(&rwlock);
{
printf("readthread1==%d
",g_nNum);
}
pthread_rwlock_unlock(&rwlock);

sleep(1);
}
}

/*讀操作,其他線程允許讀操作,不允許寫操作*/
void*fun2(void*arg)
{
while(1)
{
pthread_rwlock_rdlock(&rwlock);
{
printf("readthread2==%d
",g_nNum);
}
pthread_rwlock_unlock(&rwlock);

sleep(1);
}
}

/*寫操作,其它線程都不允許讀或寫操作*/
void*fun3(void*arg)
{
while(1)
{
pthread_rwlock_wrlock(&rwlock);
{
g_nNum++;
printf("writethread1
");
}
pthread_rwlock_unlock(&rwlock);
sleep(1);
}
}
/*寫操作,其它線程都不允許讀或寫操作*/
void*fun4(void*arg)
{
while(1)
{
pthread_rwlock_wrlock(&rwlock);
{
g_nNum++;
printf("writethread2
");
}
pthread_rwlock_unlock(&rwlock);

sleep(1);
}
}

intmain(intarc,char*argv[])
{
pthread_tThrId1,ThrId2,ThrId3,ThrId4;

pthread_rwlock_init(&rwlock,NULL);//初始化一個讀寫鎖

/*創建測試線程*/
pthread_create(&ThrId1,NULL,fun1,NULL);
pthread_create(&ThrId2,NULL,fun2,NULL);
pthread_create(&ThrId3,NULL,fun3,NULL);
pthread_create(&ThrId4,NULL,fun4,NULL);

/*等待線程結束,回收其資源*/
pthread_join(ThrId1,NULL);
pthread_join(ThrId2,NULL);
pthread_join(ThrId3,NULL);
pthread_join(ThrId4,NULL);

pthread_rwlock_destroy(&rwlock);//銷毀讀寫鎖

return0;
}

結果

be5272ee-c6aa-11ed-bfe3-dac502259ad0.png

自旋鎖

自旋鎖與互斥鎖功能相同,唯一不同的就是互斥鎖阻塞后休眠不占用CPU,而自旋鎖阻塞后不會讓出CPU,會一直忙等待,直到得到鎖

自旋鎖在用戶態較少用,而在內核態使用的比較多

自旋鎖的使用場景:鎖的持有時間比較短,或者說小于2次上下文切換的時間

自旋鎖在用戶態的函數接口和互斥量一樣,把pthread_mutex_lock()/pthread_mutex_unlock()中mutex換成spin,如:pthread_spin_init()

自旋鎖函數

linux中的自旋鎖用結構體spinlock_t 表示,定義在include/linux/spinlock_type.h。自旋鎖的接口函數全部定義在include/linux/spinlock.h頭文件中,實際使用時只需include即可

示例

include
spinlock_tlock;//定義自旋鎖
spin_lock_init(&lock);//初始化自旋鎖
spin_lock(&lock);//獲得鎖,如果沒獲得成功則一直等待
{
.......//處理臨界資源
}
spin_unlock(&lock);//釋放自旋鎖

條件變量

條件變量用來阻塞一個線程,直到條件發生。通常條件變量和互斥鎖同時使用。條件變量使線程可以睡眠等待某種條件滿足。條件變量是利用線程間共享的全局變量進行同步的一種機制。

條件變量的邏輯:一個線程掛起去等待條件變量的條件成立,而另一個線程使條件成立。

基本原理

線程在改變條件狀態之前先鎖住互斥量。如果條件為假,線程自動阻塞,并釋放等待狀態改變的互斥鎖。如果另一個線程改變了條件,它發信號給關聯的條件變量,喚醒一個或多個等待它的線程。如果兩進程共享可讀寫的內存,條件變量可以被用來實現這兩進程間的線程同步

示例

#include
#include
#include
#include

pthread_cond_ttaxicond=PTHREAD_COND_INITIALIZER;
pthread_mutex_ttaximutex=PTHREAD_MUTEX_INITIALIZER;

void*ThrFun1(void*name)
{
char*p=(char*)name;

//加鎖,把信號量加入隊列,釋放信號量
pthread_mutex_lock(&taximutex);
{
pthread_cond_wait(&taxicond,&taximutex);
}
pthread_mutex_unlock(&taximutex);

printf("ThrFun1:%snowgotasignal!
",p);
pthread_exit(NULL);
}

void*ThrFun2(void*name)
{
char*p=(char*)name;
printf("ThrFun2:%scondsignal.
",p);//發信號
pthread_cond_signal(&taxicond);
pthread_exit(NULL);
}

intmain(intargc,char**argv)
{
pthread_tThread1,Thread2;
pthread_attr_tthreadattr;
pthread_attr_init(&threadattr);//線程屬性初始化

//創建三個線程
pthread_create(&Thread1,&threadattr,ThrFun1,(void*)"Thread1");
sleep(1);

pthread_create(&Thread2,&threadattr,ThrFun2,(void*)"Thread2");
sleep(1);

pthread_join(Thread1,NULL);
pthread_join(Thread2,NULL);

return0;
}

結果

be6a4fd6-c6aa-11ed-bfe3-dac502259ad0.png

虛假喚醒

當線程從等待已發出信號的條件變量中醒來,卻發現它等待的條件不滿足時,就會發生虛假喚醒。之所以稱為虛假,是因為該線程似乎無緣無故地被喚醒了。但是虛假喚醒不會無緣無故發生:它們通常是因為在發出條件變量信號和等待線程最終運行之間,另一個線程運行并更改了條件

避免虛假喚醒

在wait端,我們必須把判斷條件和wait()放到while循環中

pthread_mutex_lock(&taximutex);
{
while(value!=wantValue)
{
pthread_cond_wait(&taxicond,&taximutex);
}
}
pthread_mutex_unlock(&taximutex);

信號量

信號量用于進程或線程間的同步和互斥,信號量本質上是一個非負的整數計數器,它被用來控制對公共資源的訪問。編程時可根據操作信號量值的結果判斷是否對公共資源具有訪問的權限,當信號量值大于0時,則可以訪問,否則將阻塞

#include

//初始化信號量
intsem_init(sem_t*sem,intpshared,unsignedintvalue);

//信號量P操作(減1)
intsem_wait(sem_t*sem);

//以非阻塞的方式來對信號量進行減1操作
intsem_trywait(sem_t*sem);

//信號量V操作(加1)
intsem_post(sem_t*sem);

//獲取信號量的值
intsem_getvalue(sem_t*sem,int*sval);

//銷毀信號量
intsem_destroy(sem_t*sem);

示例

//信號量用于同步實例
#include
#include
#include
#include

sem_tsem_g,sem_p;//定義兩個信號量
chars8Test='a';

void*pthread_g(void*arg)//此線程改變字符的值
{
while(1)
{
sem_wait(&sem_g);
s8Test++;
sleep(2);
sem_post(&sem_p);
}
}
void*pthread_p(void*arg)//此線程打印字符的值
{
while(1)
{
sem_wait(&sem_p);
printf("%c",s8Test);
fflush(stdout);
sem_post(&sem_g);
}
}
intmain(intargc,char*argv[])
{
pthread_ttid1,tid2;
sem_init(&sem_g,0,0);//初始化信號量為0
sem_init(&sem_p,0,1);//初始化信號量為1

pthread_create(&tid1,NULL,pthread_g,NULL);
pthread_create(&tid2,NULL,pthread_p,NULL);

pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
return0;
}

結果

be7776e8-c6aa-11ed-bfe3-dac502259ad0.png



審核編輯:劉清

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • cpu
    cpu
    +關注

    關注

    68

    文章

    10878

    瀏覽量

    212167
  • Linux
    +關注

    關注

    87

    文章

    11319

    瀏覽量

    209830
  • 計數器
    +關注

    關注

    32

    文章

    2256

    瀏覽量

    94700
  • 信號量
    +關注

    關注

    0

    文章

    53

    瀏覽量

    8357
  • Linux編程
    +關注

    關注

    0

    文章

    5

    瀏覽量

    632

原文標題:詳解Linux多線程中互斥鎖、讀寫鎖、自旋鎖、條件變量、信號量

文章出處:【微信號:良許Linux,微信公眾號:良許Linux】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    Linux多線程機制

    另一個帶類型的指針變量線程同步互斥同步(按照預想的順序執行)M->Y->M->Y->M->YM->YYY->M->YYY......互斥
    發表于 11-11 09:53

    Linux多線程機制

    定義變量,但不可以使用(*p = 100, p++, p--)  ///無類型指針只能賦值給另一個帶類型的指針變量  線程同步互斥  同步(按照預想的順序執行)  M->Y->M-
    發表于 01-10 14:59

    Linux多線程線程同步

    。同一進程內的線程共享進程的地址空間。通信:進程間通信IPC,線程間可以直接讀寫進程數據段(如全局變量)來進行通信——需要進程同步互斥手段的輔助,以保證數據的一致性。調度和切換:
    發表于 12-08 14:14

    多線程同步互斥有幾種實現方法

    線程同步是指線程之間所具有的一種制約關系,一個線程的執行依賴另一個線程的消息,當它沒有得到另一個線程
    發表于 08-05 06:06

    Win32多線程同步技術淺析

    簡要介紹了在Win32環境下多線程訪問共享資源時的同步機制,討論了主要的4種同步對象(臨界區、互斥元、事件、信號量),并描述了它們的優缺點,給出了使用Win32 API函數操控這4種對
    發表于 11-14 10:55 ?31次下載
    Win32<b class='flag-5'>多線程</b><b class='flag-5'>同步</b>技術淺析

    多線程與聊天室程序的創建

    多線程程序的編寫,多線程應用容易出現的問題。互斥對象的講解,如何采用互斥對象來實現多線程
    發表于 05-16 15:22 ?0次下載

    了解Linux多線程線程同步

    進程間通信IPC,線程間可以直接讀寫進程數據段(如全局變量)來進行通信——需要進程同步互斥手段的輔助,以保證數據的一致性。
    發表于 04-23 14:23 ?730次閱讀
    了解<b class='flag-5'>Linux</b><b class='flag-5'>多線程</b>及<b class='flag-5'>線程</b>間<b class='flag-5'>同步</b>

    linux多線程機制-線程同步

    ,而且可以在不同應用程序的線程之間實現對資源的安全共享。Linux通過pthread_mutex_t來定義互斥機制完成
    發表于 04-02 14:42 ?474次閱讀

    Linux多線程同步互斥量Mutex詳解

    嵌入式linux中文站向各位愛好者介紹linux常見同步方式互斥量Mutex的使用方法1. 初始化:在Linux下,
    發表于 04-02 14:45 ?309次閱讀

    Linux 多線程互斥互斥

    同步同一個進程的多個線程共享所在進程的內存資源,當多個線程在同一時刻同時訪問同一種共享資源時,需要相互協調,以避免出現數據的不一致和覆蓋等問題,
    發表于 04-02 14:47 ?272次閱讀

    Linux多線程同步

    操作。?多線程同步對于多線程程序來說,同步(synchronization)是指在一定的時間內只允許某一個
    發表于 04-02 14:47 ?419次閱讀

    三種Linux的常用多線程同步方式淺析

    嵌入式linux中文站給大家介紹三種Linux的常用多線程同步方式:互斥量,條件變量,信號量。
    發表于 05-02 14:49 ?3097次閱讀
    三種<b class='flag-5'>Linux</b><b class='flag-5'>中</b>的常用<b class='flag-5'>多線程</b><b class='flag-5'>同步</b>方式淺析

    Linux多線程編程的知識點

    Hello、Hello大家好,我是木榮,今天我們繼續來聊一聊Linux多線程編程的重要知識點,詳細談談
    發表于 04-26 17:27 ?607次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>中</b><b class='flag-5'>多線程</b>編程的知識點

    多線程同步的幾種方法

    多線程同步是指在多個線程并發執行的情況下,為了保證線程執行的正確性和一致性,需要采用特定的方法來協調線程之間的執行順序和共享資源的訪問。下面
    的頭像 發表于 11-17 14:16 ?1197次閱讀

    多線程如何保證數據的同步

    。本文將詳細介紹多線程數據同步的概念、問題、以及常見的解決方案。 一、多線程數據同步概念 在多線程
    的頭像 發表于 11-17 14:22 ?1263次閱讀
    主站蜘蛛池模板: 国产AV高清怡春院| 性奴公司 警花| 超碰在线视频97| 亚洲一区高清| 色多多污污在线播放免费| 久久午夜夜伦痒痒想咳嗽P| 国产精品久久久久久精品...| 0855福利| 成人手机在线观看| 诱咪youmiss| 美女露出逼| 国产在线精品亚洲视频在线| 办公室沙发口爆12P| 尤物久久99国产综合精品| 丝袜美女自摸| 欧美性appstin孕妇| 久久综合网久久综合| 国产乱对白精彩在线播放| 一个人色导航| 小女生RAPPER入口| 乳巨揉みま痴汉电车中文字幕动漫| 免费果冻传媒在线完整观看| 久久99久久成人免费播放| 国产美女又黄又爽又色视频网站| 超碰高清熟女一区二区| 99热在线免费观看| 91欧美秘密入口| 中文字幕成人| 一个人在线观看视频免费| 小荡娃奶真大| 丝袜美女被啪啪不带套漫画| 日日干夜夜啪蕉视频| 热99re久久精品国产首页| 欧美videos人牛交| 男人和女人一级黄色大片| 麻豆国产99在线中文| 邻居的阿2中文字版电影| 巨爆乳中文字幕爆乳区| 旧里番ovaの催○セイ活指导| 久久人妻无码毛片A片麻豆| 久久久99精品成人片中文|