Linux下線程間通訊--互斥鎖
1.互斥鎖簡(jiǎn)介
在編程中,引入了對(duì)象互斥鎖的概念,來(lái)保證共享數(shù)據(jù)操作的完整性。每個(gè)對(duì)象都對(duì)應(yīng)于一個(gè)可稱為" 互斥鎖" 的標(biāo)記,這個(gè)標(biāo)記用來(lái)保證在任一時(shí)刻,只能有一個(gè)線程訪問(wèn)該對(duì)象。
互斥鎖(Mutex)是在原子操作API的基礎(chǔ)上實(shí)現(xiàn)的信號(hào)量行為?;コ怄i不能進(jìn)行遞歸鎖定或解鎖,能用于交互上下文但是不能用于中斷上下文,同一時(shí)間只能有一個(gè)任務(wù)持有互斥鎖,而且只有這個(gè)任務(wù)可以對(duì)互斥鎖進(jìn)行解鎖。
互斥鎖是一種簡(jiǎn)單的加鎖的方法來(lái)控制對(duì)共享資源的存取,當(dāng)多個(gè)線程訪問(wèn)公共資源時(shí),為了保證同一時(shí)刻只有一個(gè)線程獨(dú)占資源,就可以通過(guò)互斥鎖加以限制,在一個(gè)時(shí)刻只能有一個(gè)線程掌握某個(gè)互斥鎖,擁有上鎖狀態(tài)的線程才能夠?qū)蚕碣Y源進(jìn)行操作。若其他線程希望上鎖一個(gè)已經(jīng)上鎖了的互斥鎖,則該線程就會(huì)掛起,直到上鎖的線程釋放掉互斥鎖為止。
2.互斥鎖相關(guān)函數(shù)
在Posix Thread中定義有一套專門用于線程同步的mutex函數(shù)。可以通過(guò)靜態(tài)和動(dòng)態(tài)兩種方式創(chuàng)建互斥鎖。
互斥鎖有三個(gè)類型可供選擇:
PTHREAD_MUTEX_TIMED_NP普通鎖(默認(rèn)鎖):
當(dāng)一個(gè)線程加鎖以后,其余請(qǐng)求鎖的線程將形成一個(gè)阻塞等待隊(duì)列,并在解鎖后按優(yōu)先級(jí)獲得鎖。這種鎖策略保證了資源分配的公平性。
PTHREAD_MUTEX_RECURSIVE_NP嵌套鎖:
允許同一個(gè)線程對(duì)同一個(gè)鎖成功獲得多次,并通過(guò)多次unlock 解鎖。如果是不同線程請(qǐng)求,則在加鎖線程解鎖時(shí)重新競(jìng)爭(zhēng)。
嵌套鎖對(duì)同一線程可以重復(fù)上鎖成功,對(duì)不同線程不能重復(fù)上鎖。
嵌套鎖在同一線程中重復(fù)上鎖,需要重復(fù)解鎖,否則其它線程將阻塞。
PTHREAD_MUTEX_ERRORCHECK_NP檢錯(cuò)鎖:
如果同一個(gè)線程請(qǐng)求同一個(gè)鎖,則返回 EDEADLK,否則與普通鎖類型動(dòng)作相同。 這樣就保證當(dāng)不允許多次加鎖時(shí)不會(huì)出現(xiàn)最簡(jiǎn)單情況下的死鎖。
檢錯(cuò)鎖的主要特點(diǎn)就是: 同一個(gè)線程無(wú)法多次重復(fù)進(jìn)行加鎖, 第一次獲取鎖成功后, 沒(méi)有解鎖的情況下, 如果繼續(xù)獲取鎖將不會(huì)阻塞, 會(huì)返回一個(gè)錯(cuò)誤值(35)。
動(dòng)態(tài)方式初始化互斥鎖:
int pthread_mutex_init(pthread_mutex_t *restrict mutex,constpthread_mutexattr_t *restrict attr);
??attr填NULL表示使用默認(rèn)屬性,創(chuàng)建普通鎖。
//靜態(tài)方式初始化互斥鎖
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
//互斥鎖上鎖,多次請(qǐng)求則會(huì)阻塞
int pthread_mutex_lock(pthread_mutex_t *mutex);
//互斥鎖上鎖,多次請(qǐng)求不會(huì)阻塞,會(huì)返回上鎖失敗錯(cuò)誤信息
int pthread_mutex_trylock(pthread_mutex_t *mutex);
//互斥解鎖
int pthread_mutex_unlock(pthread_mutex_t *mutex);
//銷毀互斥鎖
int pthread_mutex_destroy(pthread_mutex_t *mutex);
3.互斥鎖編程
3.1練習(xí)1
??1.創(chuàng)建1個(gè)線程,子線程先打印10遍hello,world,然后主線程再打印5遍”12346”,按次順序循環(huán)50次。
#include
#include
#include
/*
1.創(chuàng)建1個(gè)線程,子線程先打印10遍hello,world,然后主線程再打印5遍”12346”,按次順序循環(huán)50次。
*/
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;//靜態(tài)初始化互斥鎖1
pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;//靜態(tài)初始化互斥鎖2
void *pth_work(void *arg)
{
int i,j;
for(i=0;i<50;i++)
{
pthread_mutex_lock(&mutex);
printf("-----------子線程第%d遍-----------\n",i);
for(j=0;j<10;j++)
{
printf("hello,world\n");
}
pthread_mutex_unlock(&mutex2);
}
}
int main()
{
int i=0,j;
pthread_t pthid;
pthread_mutex_lock(&mutex2);
/*創(chuàng)建子線程*/
pthread_create(&pthid,NULL,pth_work,NULL);//創(chuàng)建線程
pthread_detach(pthid);
for(i=0;i<50;i++)
{
pthread_mutex_lock(&mutex2);//互斥鎖上鎖
printf("-----------主線程第%d遍-----------\n",i);
for(j=0;j<5;j++)//主線程打印
{
printf("123456\n");
}
pthread_mutex_unlock(&mutex);
}
pthread_mutex_destroy(&mutex);
pthread_mutex_destroy(&mutex2);
}
![pYYBAGMF2PKAWZXzAAHlP4bPJ8M761.png#pic_center](https://file.elecfans.com//web2/M00/64/C7/pYYBAGMF2PKAWZXzAAHlP4bPJ8M761.png#pic_center)
3.2練習(xí)2
??2.創(chuàng)建3線程,線程1打印A,線程2打印B,線程3打印C,按照ABC順序輸出10遍。
#include
#include
#include
/*
2.創(chuàng)建3線程,線程1打印A,線程2打印B,線程3打印C,按照ABC順序輸出10遍。
*/
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;//靜態(tài)初始化互斥鎖1
pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;//靜態(tài)初始化互斥鎖2
pthread_mutex_t mutex3 = PTHREAD_MUTEX_INITIALIZER;//靜態(tài)初始化互斥鎖3
void *pth_work(void *arg)
{
int cnt=(int *)arg;
//printf("cnt=%d\n",cnt);
for(int i=0;i<10;i++)
{
if(cnt==0)//線程1
{
pthread_mutex_lock(&mutex);
printf("A");
pthread_mutex_unlock(&mutex2);
}
if(cnt==1)//線程2
{
pthread_mutex_lock(&mutex2);
printf("B");
pthread_mutex_unlock(&mutex3);
}
if(cnt==2)//線程3
{
pthread_mutex_lock(&mutex3);
printf("C");
fflush(stdout);//刷新緩沖區(qū)
pthread_mutex_unlock(&mutex);
}
}
}
int main()
{
int i=0;
pthread_t pthid[3];
pthread_mutex_lock(&mutex2);
pthread_mutex_lock(&mutex3);
/*創(chuàng)建3個(gè)子線程*/
for(i=0;i<3;i++)
{
pthread_create(&pthid[i],NULL,pth_work,(void *)i);
}
/*等待線程結(jié)束*/
for(i=0;i<3;i++)
{
pthread_join(pthid[i],NULL);
}
printf("\n所有子線程結(jié)束,程序退出!\n");
pthread_mutex_destroy(&mutex);
pthread_mutex_destroy(&mutex2);
pthread_mutex_destroy(&mutex3);
}
運(yùn)行效果:
[wbyq@wbyq ubuntu]$ ./app
ABCABCABCABCABCABCABCABCABCABC
所有子線程結(jié)束,程序退出!
審核編輯:湯梓紅
-
Linux
+關(guān)注
關(guān)注
87文章
11351瀏覽量
210497 -
線程
+關(guān)注
關(guān)注
0文章
505瀏覽量
19763
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
Linux下線程間通訊---讀寫鎖和條件變量
![<b class='flag-5'>Linux</b><b class='flag-5'>下線程</b><b class='flag-5'>間</b><b class='flag-5'>通訊</b>---讀寫<b class='flag-5'>鎖</b>和條件變量](https://file.elecfans.com//web2/M00/65/75/pYYBAGMIwECAM9HdAACMyXIU438691.png)
Linux高級(jí)編程---互斥鎖
Linux多線程及線程間同步
Linux C多線程編程之互斥鎖與條件變量實(shí)例詳解
了解Linux多線程及線程間同步
![了解<b class='flag-5'>Linux</b>多<b class='flag-5'>線程</b>及<b class='flag-5'>線程</b><b class='flag-5'>間</b>同步](https://file.elecfans.com/web1/M00/8F/8C/pIYBAFy-rzmAMLQtAADvJf4Jl0A128.png)
Linux 多線程互斥量互斥
詳談Linux操作系統(tǒng)編程的互斥量mutex
![詳談<b class='flag-5'>Linux</b>操作系統(tǒng)編程的<b class='flag-5'>互斥</b>量mutex](https://file.elecfans.com/web1/M00/C8/B0/o4YBAF9xj5qAZUPDAACP4MF3D68654.png)
兩個(gè)線程和互斥鎖如何形成死循環(huán)?
![兩個(gè)<b class='flag-5'>線程</b>和<b class='flag-5'>互斥</b><b class='flag-5'>鎖</b>如何形成死循環(huán)?](https://file.elecfans.com/web1/M00/D4/74/o4YBAF_bGz2AFBZTAADCT5PpsW8152.png)
兩個(gè)線程,兩個(gè)互斥鎖如何形成死鎖
![兩個(gè)<b class='flag-5'>線程</b>,兩個(gè)<b class='flag-5'>互斥</b><b class='flag-5'>鎖</b>如何形成死鎖](https://file.elecfans.com/web1/M00/D7/CF/pIYBAF_pNKSADJWEAAEozAvY8jg165.png)
Linux實(shí)例:多線程和互斥鎖到底該如何使用
![<b class='flag-5'>Linux</b>實(shí)例:多<b class='flag-5'>線程</b>和<b class='flag-5'>互斥</b><b class='flag-5'>鎖</b>到底該如何使用](https://file1.elecfans.com/web2/M00/82/E4/wKgZomRlwzOAZKWEAAAmGb7QuXo412.png)
評(píng)論