Linux下線程間通訊--互斥鎖
1.互斥鎖簡介
在編程中,引入了對象互斥鎖的概念,來保證共享數據操作的完整性。每個對象都對應于一個可稱為" 互斥鎖" 的標記,這個標記用來保證在任一時刻,只能有一個線程訪問該對象。
互斥鎖(Mutex)是在原子操作API的基礎上實現的信號量行為。互斥鎖不能進行遞歸鎖定或解鎖,能用于交互上下文但是不能用于中斷上下文,同一時間只能有一個任務持有互斥鎖,而且只有這個任務可以對互斥鎖進行解鎖。
互斥鎖是一種簡單的加鎖的方法來控制對共享資源的存取,當多個線程訪問公共資源時,為了保證同一時刻只有一個線程獨占資源,就可以通過互斥鎖加以限制,在一個時刻只能有一個線程掌握某個互斥鎖,擁有上鎖狀態的線程才能夠對共享資源進行操作。若其他線程希望上鎖一個已經上鎖了的互斥鎖,則該線程就會掛起,直到上鎖的線程釋放掉互斥鎖為止。
2.互斥鎖相關函數
在Posix Thread中定義有一套專門用于線程同步的mutex函數。可以通過靜態和動態兩種方式創建互斥鎖。
互斥鎖有三個類型可供選擇:
PTHREAD_MUTEX_TIMED_NP普通鎖(默認鎖):
當一個線程加鎖以后,其余請求鎖的線程將形成一個阻塞等待隊列,并在解鎖后按優先級獲得鎖。這種鎖策略保證了資源分配的公平性。
PTHREAD_MUTEX_RECURSIVE_NP嵌套鎖:
允許同一個線程對同一個鎖成功獲得多次,并通過多次unlock 解鎖。如果是不同線程請求,則在加鎖線程解鎖時重新競爭。
嵌套鎖對同一線程可以重復上鎖成功,對不同線程不能重復上鎖。
嵌套鎖在同一線程中重復上鎖,需要重復解鎖,否則其它線程將阻塞。
PTHREAD_MUTEX_ERRORCHECK_NP檢錯鎖:
如果同一個線程請求同一個鎖,則返回 EDEADLK,否則與普通鎖類型動作相同。 這樣就保證當不允許多次加鎖時不會出現最簡單情況下的死鎖。
檢錯鎖的主要特點就是: 同一個線程無法多次重復進行加鎖, 第一次獲取鎖成功后, 沒有解鎖的情況下, 如果繼續獲取鎖將不會阻塞, 會返回一個錯誤值(35)。
動態方式初始化互斥鎖:
int pthread_mutex_init(pthread_mutex_t *restrict mutex,constpthread_mutexattr_t *restrict attr);
??attr填NULL表示使用默認屬性,創建普通鎖。
//靜態方式初始化互斥鎖
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
//互斥鎖上鎖,多次請求則會阻塞
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_destroy(pthread_mutex_t *mutex);
3.互斥鎖編程
3.1練習1
??1.創建1個線程,子線程先打印10遍hello,world,然后主線程再打印5遍”12346”,按次順序循環50次。
#include
#include
#include
/*
1.創建1個線程,子線程先打印10遍hello,world,然后主線程再打印5遍”12346”,按次順序循環50次。
*/
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;//靜態初始化互斥鎖1
pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;//靜態初始化互斥鎖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);
/*創建子線程*/
pthread_create(&pthid,NULL,pth_work,NULL);//創建線程
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);
}
3.2練習2
??2.創建3線程,線程1打印A,線程2打印B,線程3打印C,按照ABC順序輸出10遍。
#include
#include
#include
/*
2.創建3線程,線程1打印A,線程2打印B,線程3打印C,按照ABC順序輸出10遍。
*/
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;//靜態初始化互斥鎖1
pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;//靜態初始化互斥鎖2
pthread_mutex_t mutex3 = PTHREAD_MUTEX_INITIALIZER;//靜態初始化互斥鎖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);//刷新緩沖區
pthread_mutex_unlock(&mutex);
}
}
}
int main()
{
int i=0;
pthread_t pthid[3];
pthread_mutex_lock(&mutex2);
pthread_mutex_lock(&mutex3);
/*創建3個子線程*/
for(i=0;i<3;i++)
{
pthread_create(&pthid[i],NULL,pth_work,(void *)i);
}
/*等待線程結束*/
for(i=0;i<3;i++)
{
pthread_join(pthid[i],NULL);
}
printf("\n所有子線程結束,程序退出!\n");
pthread_mutex_destroy(&mutex);
pthread_mutex_destroy(&mutex2);
pthread_mutex_destroy(&mutex3);
}
運行效果:
[wbyq@wbyq ubuntu]$ ./app
ABCABCABCABCABCABCABCABCABCABC
所有子線程結束,程序退出!
審核編輯:湯梓紅
-
Linux
+關注
關注
87文章
11227瀏覽量
208924 -
線程
+關注
關注
0文章
504瀏覽量
19651
發布評論請先 登錄
相關推薦
評論